委託された非同期学習

8431 ワード

BackgroundWorkerコンポーネントの使用では、Winformプログラミングにおいて、BackgroundWorkerコンポーネントを使用して非同期呼び出しを実現することについて説明し、本稿では主に依頼を用いて非同期呼び出しを実現することについて説明する.
以下の説明はMSDNに抜粋する.
非同期委任は、同期メソッドを非同期で呼び出す能力を提供します.
同期呼び出し依頼の場合、Invoke()メソッドは現在のスレッドに対して直接ターゲットメソッドを呼び出します.
非同期呼び出し依頼の場合、CLRは要求をキューに並べて直ちに呼び出し元に戻る、スレッドプールからのスレッドに対してそのターゲットメソッドを呼び出し、要求を提出した元のスレッドは引き続きターゲットメソッドと並列に実行され、このターゲットメソッドはスレッドプールスレッドに対して実行する.
1)、BeginInvoke()メソッド
BeginInvoke()メソッドは、非同期実行が必要なメソッドと同じパラメータを持つ非同期呼び出しを開始します.
また、2つのオプションパラメータがあります.最初のパラメータは、非同期呼び出しが完了したときに呼び出すメソッドを参照するAsyncCallback依頼です.2番目のパラメータは、コールバックメソッドに情報を伝達できるユーザ定義オブジェクトです.
BeginInvokeはすぐに戻り、非同期呼び出しの完了を待たない.
BeginInvokeはIAsyncResultを返し、この結果は非同期呼び出しの進行状況を監視するために使用することができる.
2)、EndInvoke()メソッド
EndInvoke()メソッドは、非同期呼び出しの結果を取得します.
BeginInvoke()メソッドを呼び出すと、いつでもEndInvoke()メソッドを呼び出すことができます.非同期呼び出しが完了していない場合、EndInvoke()メソッドは、非同期呼び出しが完了するまで呼び出しスレッドを停止し、非同期呼び出しが完了するまで呼び出しスレッドの実行を許可しません.
EndInvoke()のパラメータには、非同期で実行されるメソッドのoutおよびrefパラメータ、およびBeginInvoke()によって返されるIAsyncResultが必要です.
 
次に、非同期委任についてコードで説明します.
コード1、同期実行:
 public delegate int MathDelegate(int x);    
public class MathClass
{
public int Add(int x)
{
Thread.Sleep(10000);//
return x + x;
}
}

public class Program
{
public static void Main(string[] args)
{
MathClass addClass = new MathClass();
MathDelegate mathDel = new MathDelegate(addClass.Add);

//
int syncResult = mathDel(8);
Console.WriteLine("Sync Proccessing operation...");// SyncMethod
Console.WriteLine("Sync Result is: {0}", syncResult);

Console.ReadLine();
}
}
int syncResult = mathDel(8); , 10 (Add ),
     ,     ,        ,           ,  Add      。

コード2、非同期実行:
Mainのコードを少し修正します.
public static void Main(string[] args)
{
MathClass addClass = new MathClass();
MathDelegate mathDel = new MathDelegate(addClass.Add);

IAsyncResult async = mathDel.BeginInvoke(9, null, null);// , Add
Console.WriteLine("Async Proccessing operation...");//
int asyncReuslt = mathDel.EndInvoke(async);
Console.WriteLine("Result is: {0}", asyncReuslt);

Console.ReadLine();
}

このコードでは、最初はメソッドを直接呼び出すのではなく、BeginInvoke()メソッドを使用してIAsyncResultオブジェクトを返します.
コード3,IsCompleted,ポーリング非同期呼び出し完了
IAsyncResultインスタンスのIsCompletedプロパティを使用して、非同期オペレーションが完了したかどうかの指示を取得します.オペレーションが完了した場合はTrue、そうでない場合はFalseです.
Mainのコードを変更します.
public static void Main(string[] args)
{
MathClass addClass = new MathClass();
MathDelegate mathDel = new MathDelegate(addClass.Add);

IAsyncResult async = mathDel.BeginInvoke(9, null, null);// , Add
Console.WriteLine("Async Proccessing operation...");//

int i = 1;
while (async.IsCompleted==false)
{
Thread.Sleep(i * 1000);
Console.WriteLine("IsCompleted:{0},{1}", async.IsCompleted, i);
i++;
}
int asyncReuslt = mathDel.EndInvoke(async);
Console.WriteLine("Result is: {0}", asyncReuslt);

Console.ReadLine();
}

コード4,AsyncCallback,非同期呼び出し完了時にコールバックを実行する方法
非同期呼び出しを開始するスレッドが結果を処理するスレッドである必要がない場合、呼び出しが完了したときにコールバックメソッドを実行できます.
コールバックメソッドを使用する場合は、参照コールバックメソッドAsyncCallbackをBeginInvoke()メソッドに委任するか、コールバックメソッドが使用する情報を含むオブジェクトを渡す必要があります.
Mainのコードを変更します.
public static void Main(string[] args)
{
MathClass addClass = new MathClass();
MathDelegate mathDel = new MathDelegate(addClass.Add);

IAsyncResult async = mathDel.BeginInvoke(9, new AsyncCallback(CompleteMethod), " ");// , Add
Console.WriteLine("Async Proccessing operation...");//
Console.ReadLine();
}
private static void CompleteMethod(IAsyncResult async)
{
AsyncResult ar = (AsyncResult)async;

MathDelegate del = (MathDelegate)ar.AsyncDelegate;
int result = del.EndInvoke(async);

string mainTheadMsg = ar.AsyncState as string;
Console.WriteLine("{0}, Result is: {1}", mainTheadMsg, result);
}
Add        ,   CompleteMethod