各位大神们,我写了一个for循环,任务是从仪表中采数,经过一个算法,把最终结果填入表格,问题是我在for循环中加了一个延时小程序,为了等待仪表输出稳定再采数,但是这样造成了我的界面假死,for循环由一个button控制开始,我加一个button任意时刻中断这个for循环,但是for循环跑起来,所有button都点不了,这要怎么解决呀,下附延时小程序
AutoResetEvent MyDelayEvent = new AutoResetEvent(false);            //定义事件 
        public  void myDealyTime(int time)
        {
            System.Timers.Timer MyDelayTimer = new System.Timers.Timer(time);   //设置定时器
            MyDelayTimer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_TimesUp);
            MyDelayTimer.AutoReset = true; //每到指定时间Elapsed事件是触发一次(false),还是一直触发(true),要用true会复位时间。
            MyDelayTimer.Enabled = true; //是否触发Elapsed事件
            MyDelayTimer.Start();
            MyDelayEvent.WaitOne();
            MyDelayTimer.Dispose();
            Console.WriteLine("aa");
 
        }
 https://blog.csdn.net/doyoucool/article/details/74516460        private void Timer_TimesUp(object sender, System.Timers.ElapsedEventArgs e)
        {
           
            MyDelayEvent.Set();
            Console.WriteLine("bb");
延时是在网上找的https://blog.csdn.net/doyoucool/article/details/74516460

解决方案 »

  1.   


    界面假死是因为主线程被阻塞了
    大多数耗时的操作和处理推荐使用
    线程或者Task来完成
    与UI交互使用委托
    如果不熟悉,可以用backgroundworker控件来实现
      

  2.   

    你在 Timer_TimesUp 中再输出 aa 就行了,myDealyTime 方法应该一瞬间就完了,为什么要卡死在那里?阻塞是最垃圾的做法。实在不会编程的人,刚学编程的人,才那样以为阻塞是简单粗暴的好办法。真正的有经验的人都知道这种简单粗暴是垃圾的。
      

  3.   


    这就是一个只会写简单的数学计算小函数的弊病。一旦开发交互操作程序,你不打算阻塞这个所谓 for 循环过程,那么你就不可能写一个同步 for 循环,你必须会学异步 for 循环。没学过异步 for 循环语句怎么写的话,那么你就设计一个 timer 来模拟 for 循环反复调用并且递加循环变量的几行代码,把这个机制封装到一个单独的对象中以免循环控制变量跟其它变量相冲突。总之,这里其实重点不在于子线程概念。即使是只能进行单线程编程(例如古老的 vb3、vb5 编程),你也是可以用定时器迭代模拟 for 循环的。关键就在于要有基本的意识,在 for 循环中必须交出 UI 控制权,绝不能阻塞。
      

  4.   


    这就是一个只会写简单的数学计算小函数的弊病。一旦开发交互操作程序,你不打算阻塞这个所谓 for 循环过程,那么你就不可能写一个同步 for 循环,你必须会学异步 for 循环。没学过异步 for 循环语句怎么写的话,那么你就设计一个 timer 来模拟 for 循环反复调用并且递加循环变量的几行代码,把这个机制封装到一个单独的对象中以免循环控制变量跟其它变量相冲突。总之,这里其实重点不在于子线程概念。即使是只能进行单线程编程(例如古老的 vb3、vb5 编程),你也是可以用定时器迭代模拟 for 循环的。关键就在于要有基本的意识,在 for 循环中必须交出 UI 控制权,绝不能阻塞。
    大神,那意思就是说我的界面假死是因为加入了那个延时程序造成阻塞引起的吗,,还是因为for循环本身就会阻塞我是崭新崭新的小白
      

  5.   


    这就是一个只会写简单的数学计算小函数的弊病。一旦开发交互操作程序,你不打算阻塞这个所谓 for 循环过程,那么你就不可能写一个同步 for 循环,你必须会学异步 for 循环。没学过异步 for 循环语句怎么写的话,那么你就设计一个 timer 来模拟 for 循环反复调用并且递加循环变量的几行代码,把这个机制封装到一个单独的对象中以免循环控制变量跟其它变量相冲突。总之,这里其实重点不在于子线程概念。即使是只能进行单线程编程(例如古老的 vb3、vb5 编程),你也是可以用定时器迭代模拟 for 循环的。关键就在于要有基本的意识,在 for 循环中必须交出 UI 控制权,绝不能阻塞。
    那我现在要解决问题的话就是要写一个异步for循环吗,那我想加一个button,在任意时刻跳出或者终止这个循环,异步for循环也是可以实现的吗
      

  6.   

    比如说"要用一个标签控件,每30秒钟刷新显示设备温度“,那么有的人就会纠结于一个"线程+死循环+阻塞Read+阻塞Sleep"这么一个过程编程概念。那么控件上至少有成千成万个需要不断改变的控件状态,界面的底层下面的代码还有更多需要持续更新的东西,你还是继续滥用线程吗?实际上这些操作都是瞬间完成的。然后结合事件通知来响应各种数据采集、事件发生的通知。因此所谓同步的阻塞过程是小孩子过家家的,程序设计师要在有限的编程语句范围之内,(即使是用只支持单线程编程模式的编程语言也)编写出异步的交互式程序流程。只有这样把对象的通讯交互变为异步的,随时可以释放当前线程给系统UI机制去使用,你的程序的 UI 才可能流畅、通讯并发性能才高。
      

  7.   

    单就定时机制来说,现在的 async/await 机制可以让我们编写await Task.Delay(500);
    后续处理代码.......这类语句来定时,但是把这个代码写到 for 循环内部,你起码应该知道机制,这个代码所在的方法的声明上要写 async 关键字,调试时一旦执行到 Delay 这里其实方法就跳出去了,方法就结束了;然后过了500毫秒又有一个线程(系统线程池分配的任务)跳进了await 的左边或者后边的代码继续调用后续处理代码。你如果不懂异步机制,就会觉得诡异,或者就会盲目抄袭而写出逻辑上有着巨大 bug 的代码。
      

  8.   

    Timer(定时器)有 Enabled 属性,令其为 false 就停止了
      

  9.   

    这原本是有关计算机体系结构、驱动层原理、操作系统CPU和任务调度原理、数据结构访问、灵活的控件事件开发、软件工程设计知识之类的基础知识都相关的综合结果。你没有学过基础课程,我已经尽量用通俗的话给你解释了概念,你自己需要理解。
      

  10.   

    for 循环里 调用 下面 函数void DoEvents()
    {
    MSG msg;
    // Process existing messages in the application's message queue.
    // When the queue is empty, do clean up and return.
    while (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
    {// has msg
    if (!AfxGetThread()->PumpMessage()) break;
    }
    }
      

  11.   

    Application.DoEvents刷新。放在线程里
      

  12.   

    Code blocks调试失败?大佬指点一下
      

  13.   

    Application.DoEvents();
      

  14.   

    再new thread中执行那个for
      

  15.   

    已经用Application.DoEvents();解决个问题,谢谢各位老师的解答
      

  16.   

    这就是一个只会写简单的数学计算小函数的弊病。一旦开发交互操作程序,你不打算阻塞这个所谓 for 循环过程,那么你就不可能写一个同步 for 循环,你必须会学异步 for 循环。没学过异步 for 循环语句怎么写的话,那么你就设计一个 timer 来模拟 for 循环反复调用并且递加循环变量的几行代码,把这个机制封装到一个单独的对象中以免循环控制变量跟其它变量相冲突。总之,这里其实重点不在于子线程概念。即使是只能进行单线程编程(例如古老的 vb3、vb5 编程),你也是可以用定时器迭代模拟 for 循环的。关键就在于要有基本的意识,在 for 循环中必须交出 UI 控制权,绝不能阻塞。
      

  17.   

    有关计算机体系结构、驱动层原理、操作系统CPU和任务调度原理、数据结构访问、灵活的控件事件开发、软件工程设计知识。哦耶,好高深的样子,朕也是醉了。
      

  18.   

    你可以new一个新的线程单独去进行这个for循环,将界面需要的数据传入这个线程,相互通信,这样主界面就不会卡死。
    我就是自学新手,我平时经常这么做,没觉得有什么不妥。
      

  19.   


    DoEvents 主要是18年前移植 vb6 的语句使用,因为 vb 当时本身的语言设计是不具有多线程编程能力的,(当时)其它平台并不进行这样的操作,哪怕是单线程的 javascript 语言也不支持 DoEvents 这类操作。正常的事件处理过程,你调试一下就知道,是正常地执行完一个事件的过程,然后才执行下一个事件处理过程。而如果在一个时间处理过程中递归调用 windows 消息泵里处理后边的事件处理过程,那么就产生了逻辑上的诡异跳转,直接跳转到其它事件处理过程之后CPU上下文又跳回递归点。这在你把 DoEvents 写到循环语句中(通常你都是干这个的)时,特别是一个事件处理过程中的操作可能会造成其它事件发生时,会迅速产生逻辑混乱,以及事件级联爆炸的危险。正常的事件处理过程是不会发生这种情况的,因为没有哪个事件处理过程在设计上是在某个中间点去递归地处理其它事件的。所以 DoEvents 其实是个大坑。这很适合 vb 那类——vb 的含义本身就是“初学者编程语言”——使用,但是复杂的事件驱动设计程序则会(即使是单线程)逻辑混乱无法调试,甚至因为事件次序的混乱而产生事件组合爆炸。
      

  20.   

    哪怕是 js 语言,它支持var x = {
       t: 0,
       start: function(){
            .......
            if(this.t<1000)
                window.setTimeout(this.start, 50);
        }
    }
            这类使用定时器的迭代循环操作。它处理循环时不是用递归,而是定时迭代,所以裸机上它一定是当前 function 运行完毕之后才执行其它的 UI 函数,所以有起码的安全。而 DoEvents 并不是基本安全的机制,不可以随便用。
      

  21.   

    只要是经常被触发的不同的事件处理过程在逻辑上相互一点纠结,你就会开始发现 DoEvents 的递归跳转机制的逻辑毛病了。而这个仅仅在你刚刚知道一点编程时时也许看不出来,但是其实对于有经验的复杂交互程序的程序设计师,其实意味着逻辑流程上的诡异和逻辑的背道而驰。