Visual C# のメソッドを非同期で呼び出す方法

概要

Microsoft.NET Framework では、関数を非同期的に呼び出す簡単。関数の非同期呼び出しは、呼び出し元の関数は、他の作業を続けながら、セカンダリ スレッドでバック グラウンドでそれらを実行するシステムです。典型的な (同期) 関数の呼び出しで関数は、呼び出しを行った同じスレッドですぐに実行されます。呼び出し元の関数は、呼び出しが完了するまで待機し、続行する前に呼び出しの結果を受け取ります。対照的に、非同期呼び出しを行うと、後での非同期呼び出しの結果を取得します。この資料では、Visual C# を使用してこれを行う方法について説明します。

要件


推奨されるハードウェア、ソフトウェア、ネットワーク インフラストラクチャ、および必要なサービス パックは、次のとおりです。
  • Microsoft Windows 2000 または Microsoft Windows XP または Windows Server 2003
  • Visual Studio .NET または Visual Studio 2005
この資料は次のトピックに精通している事を前提としています。
  • Visual C# のメソッドの呼び出し
  • デリゲートを使用する方法

非同期呼び出しを行う方法

非同期の呼び出しは、デリゲートを使用して行われます。デリゲートは、関数をラップするオブジェクトです。デリゲートは、同期機能を提供してもラップされた関数を非同期的に呼び出すためのメソッドを提供します。これらのメソッドは、 BeginInvoke()およびEndInvoke()です。これらのメソッドのパラメーター リストは、デリゲートをラップする関数のシグネチャによって異なります。Visual Studio .NET の IntelliSense 機能や表示されないBeginInvoke() EndInvoke()、それらを入力すると関数のリストに表示されますが表示されないように注意してください。


BeginInvoke()を使用して、非同期呼び出しを開始します。ラップされた関数と同じパラメーターと共に、この資料の後半で説明する 2 つの追加パラメーターを持っています。BeginInvoke()はすぐに返され、非同期呼び出しの完了を待ちません。BeginInvoke()は、 IAsyncResultオブジェクトを返します。

EndInvoke()関数を使用して、非同期呼び出しの結果を取得します。BeginInvoke()後はいつでも呼び出すことができます。非同期呼び出しが完了していない場合、完了するまでEndInvoke()はブロックされます。アウトEndInvoke()関数のパラメーターが含まれていて、
BeginInvoke()によって返されたIAsyncResultオブジェクトに加えて、ラップされた関数には、 refのパラメーターです。

デリゲートと、 BeginInvoke()EndInvoke()メソッドの例は次のとおりです。
// The following delegate delegate string MethodDelegate(int iCallTime, out int iExecThread)  ;

// will have the following BeginInvoke() and EndInvoke methods:
IAsyncResult MethodDelegate.BeginInvoke(int iCallTime, out int iExecThread, AsyncCallback cb, object AsyncState);

string MethodDelegate.EndInvoke (out int iExecThread, IAsyncResult ar) ;

BeginInvoke()EndInvoke()を使用して非同期呼び出しを作成する 4 つの一般的な方法があります。BeginInvoke()を呼び出すと、以下の操作を実行できます。
  • その他の操作を行う必要に応じて、 EndInvoke()を使用して実行してください。
  • IAsyncResultオブジェクトによって提供されているWaitHandleを取得し、[ WaitOneメソッドを使用して、 WaitHandleがシグナル状態になるまでブロックするのに、 EndInvoke()を呼び出します。
  • 非同期呼び出しが完了したらを確認し、 EndInvoke()を呼び出してするIAsyncResultオブジェクトをポーリングします。
  • 指定したコールバック関数を呼び出して、システムがあります。このコールバック関数はEndInvoke()を呼び出すし、それが完了すると、非同期呼び出しの結果を処理します。
次のコード サンプルでは、これらのパターンを呼び出すし、次の関数を使用して同期呼び出しを行うとは対照的に示しています。
string LongRunningMethod (int iCallTime, out int iExecThread){
Thread.Sleep (iCallTime) ;
iExecThread = AppDomain.GetCurrentThreadId ();
return "MyCallTime was " + iCallTime.ToString() ;
}


LongRunningMethod()では、スリープ状態で長時間実行される関数をシミュレートします。スリープ時間とそれを実行するスレッドの ID を返します。非同期的に呼び出しを実行中のスレッドのスレッド ID は呼び出し元のスレッドの場合と異なることがわかります。

最初のステップは、関数をラップしているデリゲートを定義するのには。
delegate string MethodDelegate(int iCallTime, out int iExecThread)  ;

例 1: 同期メソッドの呼び出し

このサンプルでは、 LongRunningMethod()MethodDelegateデリゲートを使用して同期的に呼び出す方法を示します。他のサンプルには、非同期的に呼び出しを行うことによってこれが対照的です。
  1. Microsoft Visual Studio .NET または Microsoft Visual Studio 2005 を起動します。
  2. AsyncDemo をという名前の新しい Visual C# コンソール アプリケーション プロジェクトを作成します。
  3. .Cs ファイル内のプロジェクトに次のように定義されている AsyncDemo をという名前のクラスを追加します。
    using System;using System.Threading ; 
    using System.Windows.Forms ;

    public class AsyncDemo
    {
    string LongRunningMethod (int iCallTime, out int iExecThread)
    {
    Thread.Sleep (iCallTime) ;
    iExecThread = AppDomain.GetCurrentThreadId ();
    return "MyCallTime was " + iCallTime.ToString() ;
    }

    delegate string MethodDelegate(int iCallTime, out int iExecThread) ;

    public void DemoSyncCall()
    {
    string s ;
    int iExecThread;

    // Create an instance of a delegate that wraps LongRunningMethod.
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;

    // Call LongRunningMethod using the delegate.
    s = dlgt(3000, out iExecThread);

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the thread ID {1}", s, iExecThread.ToString() ) );
    }
    }

    以降では、このクラスは、非同期呼び出しを行う方法を示します。最初に、ただし、のみを含む、 DemoSyncCall()メソッドは、デリゲートを同期的に呼び出す方法について説明します。
  4. Visual Studio は、プロジェクトに自動的に作成されるMain関数の本文に次のコードを追加します。
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoSyncCall() ;
    }

  5. アプリケーションを実行する ctrl キー + f5 キーを押します。

例 2: メソッドの非同期呼び出しEndInvoke()呼び出しパターンを使用して

このセクションでは、サンプルは、同じメソッドを非同期で呼び出します。BeginInvokeを呼び出すには、呼び出しパターンを使用する、いくつか、メイン スレッドで作業を行い、 EndInvoke()を呼び出します。EndInvoke()は、非同期呼び出しが完了するまで返されませんを確認します。この呼び出しパターンは便利ですが、非同期呼び出しを実行しているのと同時に作業を実行する呼び出し元のスレッドがある場合します。作業が同時に発生することと、多くのアプリケーションのパフォーマンスを向上させることができます。この方法で非同期的に実行する一般的なタスクは、ファイルやネットワーク操作です。
  1. AsyncDemoクラスにDemoEndInvoke()をという名前のメソッドを追加します。DemoEndInvoke関数では、デリゲートを非同期的に呼び出す方法を示します。
    public void DemoEndInvoke(){
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    string s ;
    int iExecThread;

    // Initiate the asynchronous call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);

    // Do some useful work here. This would be work you want to have
    // run at the same time as the asynchronous call.

    // Retrieve the results of the asynchronous call.
    s = dlgt.EndInvoke (out iExecThread, ar) ;

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the number {1}", s, iExecThread.ToString() ) );
    }

  2. 次のコードが含まれるように、メインのソース コードを編集します。
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoEndInvoke() ;
    }

  3. アプリケーションを実行する ctrl キー + f5 キーを押します。

例 3: メソッドを非同期に呼び出すと、完了するために呼び出しを待機する WaitHandle を使用して


このセクションでは、サンプルは、メソッドを非同期的に呼び出すし、 EndInvoke()を呼び出す前にWaitHandle待機します。BeginInvoke()によって返されたIAsyncResultAsyncWaitHandleプロパティがあります。このプロパティは、非同期呼び出しが完了したときに通知されるWaitHandleを返します。WaitHandleを待機するいるとは、一般的なスレッドの同期手法です。呼び出し元のスレッドは、 WaitHandleWaitOne()メソッドを使用して、 WaitHandleを待機します。WaitHandleがシグナル状態になるまでブロックをWaitOne()WaitOne()が返されるとき、 EndInvoke()を呼び出す前に、いくつか追加の作業を行うことができます。前の例のように、この手法は、呼び出し元のメイン スレッドをブロックすることがそれ以外の場合は、ファイルやネットワークの操作を実行するのに便利です。
  1. AsyncDemoクラスにDemoWaitHandle()をという名前の関数を追加します。DemoWaitHandle()関数では、デリゲートを非同期的に呼び出す方法を示します。
    public void DemoWaitHandle (){
    string s ;
    int iExecThread;

    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;

    // Initiate the asynchronous call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);

    // Do some useful work here. This would be work you want to have
    // run at the same time as the asynchronous call.

    // Wait for the WaitHandle to become signaled.
    ar.AsyncWaitHandle.WaitOne() ;

    // Get the results of the asynchronous call.
    s = dlgt.EndInvoke (out iExecThread, ar) ;

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the number {1}", s, iExecThread.ToString() ) );
    }

  2. 次のコードが含まれるように、メインのソース コードを編集します。
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoWaitHandle () ;
    }

  3. アプリケーションを実行する ctrl キー + f5 キーを押します。

例 4: メソッドの呼び出しを非同期的にポーリング呼び出しパターンを使用して

このセクションでは、サンプルは、非同期呼び出しが完了したことを検出するIAsyncResultオブジェクトをポーリングします。BeginInvoke()によって返されたIAsyncResultオブジェクトには、 Trueを返す非同期呼び出しが完了した後、 IsCompletedプロパティがあります。EndInvoke()を呼び出すことができます。この呼び出しパターンでは、アプリケーションには継続的な作業を長時間実行される関数の呼び出しによってブロックされている必要がない場合に便利です。Microsoft Windows アプリケーションでは、この例を示します。Windows アプリケーションのメイン スレッドは、非同期呼び出しの実行中にユーザー入力の処理を続行できます。呼び出しが完了したかどうかを参照してくださいに実行定期的にチェックできます。IsCompletedTrueを返す場合は、 EndInvokeを呼び出します。EndInvoke()は、非同期操作が完了するまでブロックするため、アプリケーションが呼び出されません、操作が完了したことを知っているまで。
  1. AsyncDemoクラスにDemoPolling()をという名前の関数を追加します。DemoPolling()関数では、デリゲートを非同期的に呼び出すし、プロセスが完全かどうかをポーリングを使用する方法を示します。
    public void DemoPolling(){
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    string s ;
    int iExecThread;

    // Initiate the asynchronous call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);

    // Poll IAsyncResult.IsCompleted
    while(ar.IsCompleted == false)
    {
    Thread.Sleep (10) ; // pretend to so some useful work
    }
    s = dlgt.EndInvoke (out iExecThread, ar) ;

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the number {1}", s, iExecThread.ToString() ) );
    }


  2. メインのソース コードを編集します。関数の内容を次のコードに置き換えます。
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoPolling () ;
    }

  3. アプリケーションを実行する ctrl キー + f5 キーを押します。

サンプル 5: 非同期メソッドの完了時にコールバックを実行します。

このセクションでは、サンプルは、非同期呼び出しが完了したときに、システムが実行されるBeginInvoke()関数にコールバック デリゲートを提供します。コールバックは、 EndInvoke()を呼び出すし、非同期呼び出しの結果を処理します。この呼び出しパターンは、非同期呼び出しを開始したスレッドは、呼び出しの結果を処理する必要がない場合に便利です。システムは、非同期呼び出しの完了時に元のスレッド以外のスレッドでコールバックを呼び出します。


この呼び出しパターンを使用するには、 BeginInvoke()関数の最後から 2 番目のパラメーターとして型AsyncCallbackデリゲートを渡す必要があります。BeginInvoke()にも、最後のパラメーターの入力オブジェクトを任意のオブジェクトを渡すことができますが。このオブジェクトは、それが呼び出されたときにコールバック関数を使用できます。このパラメーターの 1 つの重要な用途では、呼び出しを開始するために使用されるデリゲートを渡します。コールバック関数は、呼び出しを完了するのには、 EndInvoke()関数のデリゲートを使用できます。この呼び出しパターンは、以下に示します。
  1. AsyncDemoクラスにDemoCallback()MyAsyncCallback()をという名前の 2 つのメソッドを追加します。DemoCallback()メソッドは、デリゲートを非同期的に呼び出す方法を示します。システム呼び出しの非同期操作が完了したら、 MyAsyncCallback()メソッドをラップするのにデリゲートを使用します。MyAsyncCallback()は、 EndInvoke()を呼び出します。
    public void DemoCallback(){
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    string s ;
    int iExecThread;

    // Create the callback delegate.
    AsyncCallback cb = new AsyncCallback(MyAsyncCallback);

    // Initiate the Asynchronous call passing in the callback delegate
    // and the delegate object used to initiate the call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, cb, dlgt);
    }

    public void MyAsyncCallback(IAsyncResult ar)
    {
    string s ;
    int iExecThread ;

    // Because you passed your original delegate in the asyncState parameter
    // of the Begin call, you can get it back here to complete the call.
    MethodDelegate dlgt = (MethodDelegate) ar.AsyncState;

    // Complete the call.
    s = dlgt.EndInvoke (out iExecThread, ar) ;

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the number {1}", s, iExecThread.ToString() ) );
    }


  2. メインのソース コードを編集します。関数の内容を次のコードに置き換えます。
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoCallback() ;
    }

  3. アプリケーションを実行する ctrl キー + f5 キーを押します。
プロパティ

文書番号:315582 - 最終更新日: 2017/02/01 - リビジョン: 1

フィードバック