列表A:
public class Calculator : ISynchronizeInvoke
{
public int Add(int arg1,int arg2)
{
int threadID = Thread.CurrentThread.GetHashCode();
Trace.WriteLine( "Calculator thread ID is " + threadID.ToString());
return arg1 + arg2;
}
//ISynchronizeInvoke implementation
public object Invoke(Delegate method,object[] args)
{
public IAsyncResult BeginInvoke(Delegate method,object[] args)
{
public object EndInvoke(IAsyncResult result)
{
public bool InvokeRequired
{
}
}
//Client-side code
public delegate int AddDelegate(int arg1,int arg2);
int threadID = Thread.CurrentThread.GetHashCode();
Trace.WriteLine("Client thread ID is " + threadID.ToString());
Calculator calc;
/* Some code to initialize calc */
AddDelegate addDelegate = new AddDelegate(calc.Add);
object[] arr = new object[2];
arr[0] = 3;
arr[1] = 4;
int sum = 0;
sum = (int) calc.Invoke(addDelegate,arr);
Debug.Assert(sum ==7);
/* Possible output:
Calculator thread ID is 29
Client thread ID is 30
*/
或許你並不想進行同步調用,因為它被打包發送到另一個線程中去了。你可以通過BeginInvoke()和EndInvoke()方法來實現它。你可以依照通用的.NET非同步編程模式(asynchronous programming model)來使用這些方法:用BeginInvoke()來發送調用,用EndInvoke()來實現等待或用於在完成時進行提示以及收集返回結果。
還值得一提的是ISynchronizeInvoke方法並非安全類型。 類型不符會導致在執行時被拋出異常,而不是編譯錯誤。所以在使用ISynchronizeInvoke時要格外注意,因為編輯器無法檢查出執行錯誤。
實現ISynchronizeInvoke要求你使用一個代理來在後期綁定(late binding)中動態地調用方法。每一種代理類型均提供DynamicInvoke()方法: public object DynamicInvoke(object[]
args);
理論上來說,你必須將一個方法代理放到一個需要提供對象運行的真實的線程中去,並使Invoke() 和BeginInvoke()方法中的代理中調用DynamicInvoke()方法。ISynchronizeInvoke的實現是一個非同一般的編程技巧,本文附帶的源文件中包含了一個名為Synchronizer的幫助類(helper class)和一個測試程序,這個測試程序是用來論證列表A中的Calculator類是如何用Synchronizer類來實現ISynchronizeInvoke的。Synchronizer是ISynchronizeInvoke的一個普通實現,你可以使用它的派生類或者將其本身作為一個對象來使用,並將ISynchronizeInvoke實現指派給它。
用來實現Synchronizer的一個重要元素是使用一個名為WorkerThread的嵌套類(nested class)。WorkerThread中有一個工作項目(work item)查詢。WorkItem類中包含方法代理和參數。Invoke()和BeginInvoke()用來將一個工作項目實例加入到查詢裡。WorkerThread新建一個.NET worker線程,它負責監測工作項目的查詢任務。查詢到項目之後,worker會讀取它們,然後調用DynamicInvoke()方法。