跨线程边界进行过程调用

跨线程边界进行过程调用

Windows 窗体控件仅可在创建它们的线程上执行,即它们不是线程安全的。如果要从后台线程获取或设置控件的属性或对控件调用方法,则必须将调用封送到创建该控件的线程。

在控件上有五个函数对于从任何线程调用都是安全的:InvokeRequiredInvokeBeginInvoke EndInvokeCreateGraphics。对于所有其他方法调用,应使用上述调用方法之一。

默认情况下,Windows 为您封送调用。但是,如果对某控件进行多次调用,则您自己创建一个执行这些调用的方法并且进行跨线程调用将有效得多。通过调用 Control.Invoke 方法之一进行跨线程调用。Invoke 方法采用对委托的引用。通常,此委托是 MethodInvoker 委托的一个实例。

InvokeRequired

public bool InvokeRequired { get ; }

如果调用方对此控件进行方法调用时必须调用 Invoke,则返回真。

BeginInvoke

public IAsyncResult BeginInvoke(Delegate method)
public IAsyncResult BeginInvoke(Delegate method, Object[] args)

在拥有此控件的基础窗口句柄的线程上执行给定的委托。异步调用该委托并且该方法立即返回。可从任何线程调用此方法,甚至可以从拥有该控件的句柄的线程上调用。如果该控件的句柄尚不存在,将沿该控件的父链向上查找,直到找到确实有窗口句柄的控件或窗体。如果无法找到相应的句柄,BeginInvoke 将引发异常。此委托方法中的异常被视为未捕获的异常,将发送给应用程序的未捕获的异常处理程序。

EndInvoke

public Object EndInvoke(IAsyncResult asyncResult)

检索由传递的 IAsyncResult 接口所代表的异步操作的返回值。如果尚未完成异步操作,此函数将阻塞,直至结果可用。

 

Invoke

public Object Invoke(Delegate method)
public Object Invoke(Delegate method, Object[] args)

在拥有此控件的基础窗口句柄的线程上执行给定的委托。同步调用该委托并且此方法在调用的方法返回后立即返回。返回值是调用的方法的结果。在控件所属的同一个线程上调用此方法是错误的。


下面的示例演示如何创建一个后台线程,该线程使用 MethodInvoker 以固定时间间隔更新 ProgressBar 控件:

 1 .
 2
 3   // Start the background thread
 4  timerThread  =   new  Thread( new  ThreadStart(ThreadProc));
 5  timerThread.IsBackground  =   true ;
 6  timerThread.Start();
 7
 8  .
 9
10   // This function is executed on a background thread - it marshalls calls to
11   // update the UI back to the foreground thread
12   public   void  ThreadProc()  {
13
14     try {
15         MethodInvoker mi = new MethodInvoker(this.UpdateProgress);
16         while (true{
17
18             //Call BeginInvoke on the Form
19             this.BeginInvoke(mi);
20             Thread.Sleep(500) ;
21         }

22     }

23     //Thrown when the thread is interupted by the main thread - exiting the loop
24     catch (ThreadInterruptedException e) {
25         //Simply exit.
26     }

27     catch (Exception we) {
28     }

29 }

30
31  .
32
33   // This function is called from the background thread
34   private   void  UpdateProgress()  {
35
36     //Reset to start if required
37     if (progressBar1.Value == progressBar1.Maximum) {
38         progressBar1.Value = progressBar1.Minimum ;
39     }

40
41
42     //Reset to start if required
43     progressBar1.PerformStep() ;
44 }

45
46  .
47
48   // Make sure we clean up the background thread in Dispose
49   public   override   void  Dispose()  {
50    if (timerThread != null{
51        timerThread.Interrupt();
52        timerThread = null;
53    }

54
55    base.Dispose();
56}

57

你可能感兴趣的:(跨线程边界进行过程调用)