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<> 类型的事件 - 但您可以轻松地调整它们以适用于不同的签名委托。首先,辅助函数 (EventToATaskAsync) 采用加法器和移除器委托来设置/取消设置事件:

请注意,使用此机制的缺点是您需要为每个包装的异步操作编写扩展方法。

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 回答