4

「同期」コード (つまり、Windows イベントを使用して、他のスレッドが何かを完了するまで待機する) を「非同期」コード (デリゲートを使用してコールバック メカニズムを実装する) にリファクタリングしています。

同期コードには、待機が終了した後に使用する必要があるローカル変数が含まれていることがあります。そのようなコードが非同期になると、それらのローカル変数は失われます (コールバック ハンドラーはそれらにアクセスできません)。クラス属性として保存できますが、もったいない気がします。

C++ では、std::bindこれを回避するために使用します。コールバック ハンドラーに必要なローカル変数と同じ数のパラメーターを追加し、非同期メソッドを呼び出すときにそれらをバインドします。たとえば、非同期メソッドのコールバックが 型のオブジェクトを受け取り、呼び出し元が型とCallbackParamの 2 つのローカル変数を使用するとします。LocalALocalB

void AsyncClass::MethodWhichCallsAsyncMethod(){
    LocalA localVarA;
    LocalB localVarB;
    // OnAsyncMethodDone will need localVarA and localVarB, so we bind them
    AsyncMethod( std::bind( &AsyncClass::OnAsyncMethodDone, this, std::placeholders::_1, localVarA, localVarB ) );
}

void AsynClass::AsyncMethod( std::function<void(CallbackParam)> callback ){
    CallbackParam result;
    //Compute result...
    if( callback )
        callback( result );
}

void AsyncClass::OnAsyncMethodDone( CallbackParam p, LocalA a, LocalB b ){
   //Do whatever needs to be done
}

C# と VB.NET でこれに相当するものはありますか? デリゲートなどを使用していますか?

更新: 完全を期すために、@lasseespeholt の回答に基づいた私の例に相当する C# を次に示します。

using System;

public class AsyncClass {

        public void MethodWhichCallsAsyncMethod() {
            var a = new LocalA();
            var b = new LocalB();
            //Anonymous callback handler (equivalent to AsyncClass::OnAsyncMethodDone)
            Action<CallbackParam> callback = result => {
                //Do what needs to be done; result, a and b can be accessed
            };
            AsyncMethod( callback );
        }

        private void AsyncMethod( Action<CallbackParam> callback ) {
            var result = new CallbackParam();
            //Compute result...
            if( callback != null )
                callback( result );
        }
}
4

1 に答える 1

3

更新: これはほぼ確実に使用しないでください。C# で async/await キーワードを使用する

次のようなクロージャーを悪用できます。

void MethodWhichCallsAsyncMethod()
{
    int foo = 1;

    AsyncCallback callback = result =>
    {
        Console.WriteLine(foo); // Access to foo
    };

    AsyncMethod(callback);
}

void AsyncMethod(AsyncCallback callback)
{
    IAsyncResult result = null; // Compute result
    callback(result);
}

コンパイラは「foo」を含むクラスを生成するため、このアプローチでは何も保存されませんが、クリーンです。

于 2013-04-05T19:25:54.850 に答える