2017-11-23 19 views
-1

は、次のコードサンプルを考慮した結果を返したい、私はラムダ関数の戻り値を待つと

public XYZ GetSomething(string pluginId, string arg1, string arg2) 
    { 
     var plugin = (PluginType)_pluginManager.GetPlugin(pluginId, false); 

     plugin.RegisterCallback(result => 
     { 
      //return this object instance of type XYZ 
      return result; 
     }); 

     plugin.RequestData(arg1, arg2); 

     return null; 
    } 

は、どのように私はこのメソッドの非同期を作成し、ラムダ関数の結果を待つとせずに結果を返すことができますこの方法をブロッキング法に変える? RequestDatapluginは非ブロックであり、変更できません。 resultが最終的に返され、オブジェクト・インスタンスであり、どのタスクにもラップされません。

ラムダ関数の結果を待ってから、結果を返すにはどうすればよいですか?

編集: RequestData非常に迅速に完了します。リモートサーバーからデータを要求した後、数秒から数分かかるデータが返されると、コールバックを呼び出します。

+0

あなたはちょうどその引数リストの前に「非同期」のキーワードを入れて非同期(async)ラムダ式をマークすることができますが、私はRegisterCallbackがパラメータとして非同期デリゲートを受け入れる疑う:あなたのGetSomething()メソッド内でこれらの事をラップするには、TaskCompletionSource使用することができます。 –

+0

@ Marc-AntoineJacobはあまり待たずに使用しています –

+0

@TimRutter明らかに、それは私の意図ですが、RegisterCallbackはタスクを待っている非同期の代理人を受け入れません。 –

答えて

4

async awaitで使用できるものを作成するには、Taskを作成する必要があります。だから、メソッドはTask<XYZ>を返す必要があります。次のステップでは、あなたの.RequestData()メソッドがどのように動作するかによって異なります。それはブロックされるかどうか?最初にコールバックを登録するアーキテクチャーのために、私は.RequestData()がすぐに戻り、完了したらコールバックを呼び出すと思います。

public static void Main() 
{ 
    Console.WriteLine("Starting"); 
    Start(); 

    Console.ReadKey(); 
} 

public static async Task Start() 
{ 
    var result = await GetSometing("abc", "def", "ghi"); 
    Console.WriteLine(result); 
} 


public static Task<int> GetSometing(string pluginId, string arg1, string arg2) 
{ 
    var plugin = new PluginMock(); 
    var tcs = new TaskCompletionSource<int>(); 

    plugin.RegisterCallback(result => 
    { 
     tcs.SetResult(result); 
    }); 

    plugin.RequestData(arg1, arg2); 

    return tcs.Task; 
} 

public class PluginMock 
{ 
    private Action<int> _callback; 

    public void RegisterCallback(Action<int> callback) 
    { 
     _callback = callback; 
    } 

    public void RequestData(string arg1, string arg2) 
    { 
     var thread = new Thread(() => 
     { 
      Thread.Sleep(1000); 
      _callback(42); 
     }); 

     thread.Start(); 
    } 
} 
+0

'RequestData'はブロックされません。私は自分の質問を編集し、その情報を追加しました。それは非常に迅速に戻りますが、コールバックの呼び出しは数秒から数分かかることがあります。 –

+0

@MattWolf彼は彼の答えでこれを認めています。非常にしっかりしていますが、作業にはちょっと渋いですが、それを考えれば新しいスレッドが作成されます。 –

+0

新しいスレッドは作成されません。プラグインで起こっているいくつかの非同期のことを真似する 'PluginMock'だけです。ユーザが行う必要があるのは、 'GetSomething()'メソッド内です。 – Oliver