资源同步问题之防止界面假死

效果



代码下载



代码

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;


namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void BtnBeginInvoke_Click(object sender, EventArgs e)
        {
            //接收指令后马上开一个新线程去执行后立即返回,防止界面假死  
            System.Threading.ThreadPool.QueueUserWorkItem(o => DoByBeginInvoke());
            Debug.WriteLine("BtnBeginInvoke_Click;Thread ID:{0}", Thread.CurrentThread.ManagedThreadId);//输出为9,表示UI线程的ID为9
        }

        void DoByBeginInvoke()
        {
            //模拟执行一个花费时间很长的业务  
            System.Threading.Thread.Sleep(5000);
            Debug.WriteLine("DoByBeginInvoke;Thread ID:{0}", Thread.CurrentThread.ManagedThreadId);//输出为10,表示当前代码未在UI线程上执行

            //专心更新界面  
            //此处的方法体依然在UI线程中完成执行,所以不要将其它非UI更新的操作放在里面,比如上面的模拟  
            LblCounter1.BeginInvoke(new Action(() =>
            {
                LblCounter1.Text = (int.Parse(LblCounter1.Text) + 1).ToString();
                Debug.WriteLine("LblCounter1.BeginInvoke;Thread ID:{0}", Thread.CurrentThread.ManagedThreadId);//输出为9,表示当前代码在UI线程上执行
            }));
            LblCounter2.BeginInvoke(new Action(() =>
            {
                LblCounter2.Text = (int.Parse(LblCounter2.Text) + 1).ToString();
                Debug.WriteLine("LblCounter2.BeginInvoke;Thread ID:{0}", Thread.CurrentThread.ManagedThreadId);//输出为9,表示当前代码在UI线程上执行
            }));
        }


        private void BtnSynchronizationContext_Click(object sender, EventArgs e)
        {
            //接收指令后马上开一个新线程去执行后立即返回,防止界面假死  
            System.Threading.ThreadPool.QueueUserWorkItem(DoBySynchronizationContext, System.Threading.SynchronizationContext.Current);
            Debug.WriteLine("BtnSynchronizationContext_Click;Thread ID:{0}", Thread.CurrentThread.ManagedThreadId);//输出为9,表示当前代码在UI线程上执行
        }

        void DoBySynchronizationContext(object state)
        {
            //模拟执行一个花费时间很长的业务  
            System.Threading.Thread.Sleep(5000);
            Debug.WriteLine("DoBySynchronizationContext;Thread ID:{0}", Thread.CurrentThread.ManagedThreadId);//输出为10,表示当前代码未在UI线程上执行

            var synchronizationContext=state as System.Threading.SynchronizationContext;
            synchronizationContext.Post(o =>
            {
                //专心更新界面
                //此处的方法体依然在UI线程中完成执行,所以不要将其它非UI更新的操作放在里面,比如上面的模拟  
                LblCounter1.Text = (int.Parse(LblCounter1.Text) + 1).ToString();
                LblCounter2.Text = (int.Parse(LblCounter2.Text) + 1).ToString();
                Debug.WriteLine("synchronizationContext.Post;Thread ID:{0}", Thread.CurrentThread.ManagedThreadId);//输出为9,表示当前代码在UI线程上执行
            }, null);
        }
    }
}


备注

线程执行时第一个控件被创建时,其SynchronizationContext.Current自动会被装上一个WindowFormsSynchronizationContext。

WindowFormsSynchronizationContext对象内部创建了一个Control,用于提供Invoke和BeginInvoke来帮助实现SynchronizationContext的Send或Post。

posted @ 2012-03-19 14:54  beta2013  阅读(203)  评论(0编辑  收藏  举报