0

asyncを使用せず、従来のスレッドとコールバックを使用するマルチスレッド ライブラリを使用しています。

var connection = new SomeLib();
connection.OnConnected += (x) => { /* This is called from separate thread */ }
connection.Connect();

async次のように、関数からこのコードを呼び出しています。

public async Task<Boolean> MyFunc()
{
    var connection = new SomeLib();
    connection.OnConnected += (x) => { /* This is called from separate thread */ }
    connection.Connect();

    // ...

    // Need to return after OnConnected has been fired. 
    return true;
}

awaitコールバックが呼び出されるまで関数を「待機」させるにはどうすればOnConnectedよいですか?

4

2 に答える 2

3

以下は EventHandler<> タイプのイベントで機能しますが、さまざまなシグネチャ デリゲートで機能するように簡単に調整できます。

このメカニズムを使用することの欠点は、ラップされた非同期操作ごとに拡張メソッドを記述する必要があることです。

public static Task<A> EventToTaskAsync<A>(Action<EventHandler<A>> adder, Action<EventHandler<A>> remover)
{
    System.Threading.Tasks.TaskCompletionSource<A> tcs = new TaskCompletionSource<A>();
    EventHandler<A> onComplete = null;
    onComplete = (s, e) =>
    {
        remover(onComplete);
        tcs.SetResult(e);
    };
    adder(onComplete);
    return tcs.Task;
}

次に、通常は拡張呼び出しでラップして、Task 機能を既存のクラスに追加します。次の例では、BeginAsync をストーリーボードに追加しています (ただし、イベント メカニズムを使用するほとんどすべてのものに対してこれを行うことができます)。

    public static Task BeginAsync(this Storyboard storyboard)
    {
        return EventToTaskAsync<object>(
                e => { storyboard.Completed += e; storyboard.Begin(); },
                e => storyboard.Completed -= e);
    }

それが役立つことを願っています。

于 2013-10-09T08:39:16.477 に答える
-1

これは、待機ハンドルを使用して行うことができます。最初に AutoResetEvent を定義します。

private waitForConnect = new AutoResetEvent(false);

OnConnected ハンドラーで、ハンドルをトリガーします。

waitForConnect.Set();

connect を呼び出す関数で、ハンドルがトリガーされるのを待ちます。

connection.Connect();
waitForConnect.WaitOne(); // This will sleep the thread until connected
于 2013-10-09T08:37:31.623 に答える