首页 > 代码库 > 异步调用误区

异步调用误区

最近在优化代码的时候发现了一些问题,多是开启异步线程出现的一些问题,具体就是某个耗时操作的结果需要更新界面控件的值。

 

大概的方法就是利用Control.Invoke(delegate())这样的方法去解决跨控件访问问题,但问题也出在这里了

        void SendEditedNepImage1(bool obj)        {            if (this.InvokeRequired)            {                this.Invoke((Action)delegate()                {                    SendEditedNepImageImp1(obj);                });            }            else            {                SendEditedNepImageImp1(obj);            }        }

 

        void SendEditedNepImageImp1(bool obj)        {            for (int i = 0; i < 1000000; i++)            {                if (i == 1000000 - 1)                {                    label1.Text = i.ToString();                }            }        }

 

这样的办法看上去是解决了跨线程访问控件的问题了,有人会说你可以用BeginInvoke 加委托的方式啊,但事实真的如此吗?

让我们先来看看BeginInvoke 和Invoke的具体含义吧:

Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托。

Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句柄所在线程上异步执行指定委托。

按照这个定义去理解,只要是主线程创建的控件,你想用异步线程去操作它,最终又回到了创建它的线程,也就是UI线程,因为我的label就是主线程创建的,可能BeginInvoke会好些,它是异步的,但是也是在主线程下,对于即时性强的程序来说还是不可取,要不我们来解决它吧,这是我自己摸索的办法,也不知道靠不靠谱,我来改改吧,这样子改至少界面不卡了。

 

        void Relute()        {            string ss = string.Empty;            for (int i = 0; i < 1000000000; i++)            {                if (i == 1000000000 - 1)                {                    ss = i.ToString();                }            }            if (this.InvokeRequired)            {                this.Invoke((Action)delegate()                {                    label1.Text = ss;                });            }            else            {                label1.Text = ss;            }        }        /// <summary>        /// 模拟图片发送        /// </summary>        /// <param name="obj"></param>        void SendEditedNepImageImp(bool obj)        {            Thread th = new Thread(() => Relute());            th.Start();        }

 

好了不多说了,很简单的东西,看了就明白了。

 

异步调用误区