C# Winform 定时执行的方式(间歇休眠无卡顿)

in 桌面应用 with 0 comment

本文主要介绍两种防止WinForm界面假死卡顿的方法。其中DoEvents对于界面休眠更好(UI)不会卡顿,BeginInvoke对于需要暂停、开始的操作更友好。

调用方法:DoEvents

定义一个休眠函数,这样方便使用的时候调用,函数代码如下:

    public static void Delay(int mm) {
        DateTime crrent = DateTime.Now;
        while (crrent.AddMilliseconds(mm) > DateTime.Now) {
            Application.DoEvents();
        }
        return;
    }

需要调用是,直接:Delay(1000) # 此时休眠一秒
使用DoEvents进行开始、暂停操作时,可能会存在UI更新不及时的问题,即点击一下“停止”按钮可能还在运行,需要点击两次,一下啊方法就没有这种现象。

使用BeginInvoke和Invoke

多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法。而Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界面显示。
正确的做法是将工作线程中涉及更新界面的代码封装为一个方法,通过 Invoke 或者 BeginInvoke 去调用,两者的区别就是一个导致工作线程等待,而另外一个则不会。
Control的Invoke和BeginInvoke 是相对于支线线程(因为一般在支线线程中调用,用来更新主线程ui)Invoke立即插入主线程中执行,而BeginInvoke 要等主线程结束才执行。参看博文:http://www.cnblogs.com/c2303191/articles/826571.html

代码如下:

    bool runFlag = true;
    /// <summary>
    /// 后台要执行的操作
    /// </summary>
    private void TestInvoker()
    {
        int i = 0;
        while (runFlag)
        {

                this.TestTextBox.Invoke((Action<int>)delegate(int a) //在控件对象所在的线程上执行委托
                {
                    this.TestTextBox.AppendText(a.ToString() + "\n");
                }, i);
            i += 1;
            Thread.Sleep(500);
        }
    }
    private void StartButton_Click(object sender, EventArgs e)
    {
        runFlag = true;
        ((Action)TestInvoker).BeginInvoke(null, null); //调用委托的异步执行方法,回调函数为空 
    }

    private void StopButton_Click(object sender, EventArgs e)
    {
        runFlag = false;
    }

其实使用第一种方法就好了,页面不会卡顿并且简单。

Responses