这段时间做WinForm 有些地方加载时间太长给人的感觉很不爽,无奈仿照web的loading及Ajax异步加载。

刚开始用多线程,结果未遂,提示线程安全(不是创建控件的线程无法访问)

然后用异步委托,虽然实现了异步加载但是代码一点都不好看,偶然间发现有位前辈用Application.DoEvents(),查询发现能实现同样的效果只是不能放到线程中,当然效果是一样的。

现在把代码和测试效果贴上:

形式1:正常的10000次循环,界面卡死知道循环10000次然后显示执行结果。一般1300左右,最长1900左右。

subprocess 异步 异步显示_subprocess 异步

subprocess 异步 异步显示_i++_02

View Code

Stopwatch stw = new Stopwatch();

stw.Start();

for (int i = 0; i < 10000; i++)

{

label5.Text = i.ToString();

}

stw.Stop();

button5.Text = stw.ElapsedMilliseconds.ToString();

形式2:界面正常每一次都让主线程继续 label1 动态显示。--正常显示,当运行软件多时用时7000毫秒,一般在6500左右,最低到达6300左右。

Stopwatch stw = new Stopwatch();
            stw.Start();
for (int i = 0; i < 10000; i++)
            {
                label1.Text = i.ToString();
                Application.DoEvents();
            } 
            stw.Stop();
            button1.Text = stw.ElapsedMilliseconds.ToString();

形式3:用线程池线程执行调用主线程异步显示执行结果。--极少几率出现极短暂停顿,打开好多软件,好多网页,还未完全打开是这中形式改用label2.Invoke用时10000毫秒,一般6500毫秒左右,最低5900左右,应该是很稳定的一种。

ThreadPool.QueueUserWorkItem(new WaitCallback((a) =>
            {
                Stopwatch stw = new Stopwatch();
                stw.Start();
for (int i = 0; i < 10000; i++)
                {
this.Invoke(new MethodInvoker(() =>
                    {
                        label2.Text = i.ToString();
                    }));
                }
                stw.Stop();
this.Invoke(new MethodInvoker(() =>
                {
                    button2.Text = stw.ElapsedMilliseconds.ToString();
                }));
            }));
            button2.Text = "ThreadStart";

形式4:用新线程执行调用主线程异步显示执行结果。--基本不会卡壳在正常情况下速度最慢的7000毫秒左右

Thread th = new Thread(new ThreadStart(() =>
            {
                Stopwatch stw = new Stopwatch();
                stw.Start();
for (int i = 0; i < 10000; i++)
                {
                    label4.Invoke(new MethodInvoker(() =>
                    {
                        label4.Text = i.ToString();
                    }));
                }
                stw.Stop();
this.Invoke(new MethodInvoker(() =>
                {
                    button4.Text = stw.ElapsedMilliseconds.ToString();
                }));
            }));
            th.Start();

形式5:不用线程但是动态的调用创建控件的句柄执行委托。--来不急显示就到下次循环了一般比形式1稍多点时间。

Stopwatch stw = new Stopwatch();
            stw.Start();
for (int i = 0; i < 10000; i++)
            {
                label6.Invoke(new MethodInvoker(() =>
                {
                    label6.Text = i.ToString();
                }));
            }
            stw.Stop();
this.Invoke(new MethodInvoker(() =>
            {
                button6.Text = stw.ElapsedMilliseconds.ToString();
            }));
            button6.Text = "ThreadStart";

呵呵,明天测试下委托和匿名委托的性能差异,还有List<T>.ForEach 和foreach 的差异。

话说今天看一视频说vs2010,看到里面好多东西用起来简单多了,不过我怎么感觉不利于程序员的发展。

比如重载都穿马甲了。

int GetModel(int id=11,string name="admin",bool state=false)
{
  return 0;
}

调用居然可以 GetModel(),GetModel(name="text"),GetModel(state=true),GetModel(id=1,state=false)

太神奇了,不过好像是那个脚本框架有点像。

本人是新手在文章中的诸多错误和不足之处还望大家指出,非常感谢。

交流使人强大。