使用BackGroundWorker在多线程中访问Winform控件,当不是创建这个控件的线程访问控件时,把线程调整到是创建这个控件的线程去控制。,代码为红色的

多线程访问控件在网上的方法有很多,这里只记录我用到的这个,其他的可以去网上搜索,很多。

首先声明一个全局变量和一个委托类型(用来访问控件)


 

01.private BackgroundWorker _bWorker;  
02.delegate void SetProgressBarDelegate(int value);

在一个按钮事件里面给这个workfer赋值一些属性

01._bWorker = new BackgroundWorker();  
02.            _bWorker.DoWork += new DoWorkEventHandler(bWorker_DoWork);  
03.            _bWorker.WorkerReportsProgress = true;  
04.            _bWorker.WorkerSupportsCancellation = true;  
05.  
06.            _bWorker.RunWorkerAsync();  
07.            _bWorker.ProgressChanged += delegate(object s, ProgressChangedEventArgs ex)  
08.            {  
09.                if (proBarState.InvokeRequired)  
10.                {  
11.                    SetProgressBarDelegate setProgressBar = new SetProgressBarDelegate(delegate(int value)  
12.                    {  
13.                        proBarState.Value = ex.ProgressPercentage;  
14.                    });  
15.                    this.Invoke(setProgressBar);  
16.                }  
17.                else  
18.                {  
19.                    proBarState.Value = ex.ProgressPercentage;  
20.                }  
21.            };  
22.            _bWorker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs ex)  
23.            {  
24.                  
25.                  
26.                if (ex.Cancelled)  
27.                {  
28.                    lblState.Text = "dd";  
29.                    proBarState.Value = 0;  
30.                }  
31.                else  
32.                {  
33.                    lblState.Text = "ss";  
34.                }  
35.            }; 

  

01.void bWorker_DoWork(object sender, DoWorkEventArgs e)  
02.        {  
03.              
04.            //function to do work  
05.            if (_bWorker.CancellationPending)  
06.            {  
07.                e.Cancel = true;  
08.            }  
09.        }  

  

上面的代码最重要的部分是红字的那this.Invoke(setProgressBar);这句话的意思是winfrom应用程序的主线程(创建控件的那个线程)给控件赋值。this代表主线程。

InvokeRequired属性查找msdn:获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。也就是说如果控件位于创建控件的线程(主线程)之外,就需要使用invoke方法将操作控件的方法推送到合适的线程(主线程)中执行。

还有一个设置什么全局属性的(忘了,大意是不检测跨线程访问控件安全性的,那个是全局属性,一个地方设置了其他都是如此,在其他需要检测安全性的地方容易出bug),那个不可取。

原文地址:https://www.cnblogs.com/xiaofengfeng/p/2278136.html