等待在异步方法中调用回调

时间:2021-02-07 16:45:03

标签: c# async-await

假设我有以下订阅事件的方法。事件发生时会调用回调。我想阻止我的方法返回,直到回调被调用,或者在 10 秒过去之后。

public async Task<string> GetImportantString()
{
    string importantResult = null;
    await SubscribeToEvent("some event", async (message) =>
    {
        importantResult = message; // When "some event" happens, callback is called and we can set importantResult 
    }

    return message; // Only return when the callback is called, or 10 seconds have passed
}

SubscribeToEvent() 的签名如下:

public Task SubscribeToEvent(string event, Action<string> handler);

我使用方法 GetImportantString() 的方式如下:

public void SomeMethod() 
{
    // Do some things
    var importantString = await GetImportantString();
   // Do other things
}

问题是,在调用回调之前,我找不到不从 GetImportantString() 返回的方法。理想情况下,我想等到回调调用最多 10 秒,如果回调未在 10 秒内调用,则返回错误。如何在调用回调之前暂停 GetImportantString() 的执行?

1 个答案:

答案 0 :(得分:2)

看看这个:

public async Task<string> GetImportantString()
{
    string importantResult = null;
    using (var sph = new SemaphoreSlim(0, 1))
    {
        await SubscribeToEvent("some event", async (message) =>
        {
            importantResult = message; // When "some event" happens, callback is called and we can set importantResult 
            sph.Release();
        });

        var t = sph.WaitAsync();

        if (await Task.WhenAny(t, Task.Delay(10000)) == t)
        {
            return importantResult;
        }
    }
    throw new TimeoutException(); // whatever you want to do here
}

我们使用 SemaphoreSlim 来表示字符串何时被设置。

此时,我们等待 Task.WhenAny,它让我们知道信号量何时释放或延迟任务结束。如果信号量释放,我们可以安全地假设字符串已经设置并返回。

相关问题