【问题标题】:How can I await until I receive a callback/notification without busy-waiting?在没有忙等待的情况下,我如何等待直到收到回调/通知?
【发布时间】:2021-08-09 04:55:30
【问题描述】:

我了解如何在库代码上await 以等待网络请求或其他长时间运行的操作完成,但我如何在自己的长时间运行操作上await 无需忙于等待?


这是忙碌等待的解决方案。我怎样才能使它成为事件驱动的?

public async Task<DataBlock> ClickSend() {
    // await until someone calls DataReceived()
    while (_Block == null) {
        await Task.Yield();
    }
    return _Block;
}

// Something external calls this function.
// Once called, ClickSend should complete with this data.
public void DataReceived(DataBlock data_block) {
    _Block = data_block;
}
DataBlock _Block = null;

(这个问题与How do I await events in C#? 完全不同,How do I await events in C#? 询问如何等待事件处理程序,但与Promise equivalent in C# 非常相似。)

【问题讨论】:

  • @PeterDuniho:How do I await events in C#? 上的答案都没有建议使用TaskCompletionSource。我同意这两个问题似乎在问同一个问题,但意图却大不相同。我不关心 event 关键字的异步行为,他们也不关心 TaskCompletionSource。
  • 您说得对,答案与“什么是 C# 中的承诺”非常相似,但是如果您不知道自己在寻找什么(承诺) 并且问题是用另一种语言表达的。我提出这个问题是因为它没有那种背景,所以它更广泛有用。 (我没有看到您所指的任何“这可能是重复的”链接——只是您的评论。)
  • 您可以看到帖子here 的修订历史记录,其中显示了我错误地用于重复目标的帖子,然后是我之后添加的正确的帖子。很遗憾,我没有注意到第一个链接的错误,因为那也是我修复它的正确时间。

标签: c# async-await event-driven


【解决方案1】:

Generally in concurrency "future" 是返回值的占位符,它有一个关联的 "promise" 被履行以传递最终返回值。

在 C# 中,它们有不同的名称:future 是一个 Task 和 the promise is a TaskCompletionSource

你可以创建一个promise,等待它,然后在你收到回调时实现它:

TaskCompletionSource<DataBlock> _Promise = new TaskCompletionSource<DataBlock>();

public async Task<DataBlock> ClickSend() {
    DataBlock block = await _Promise.Task;
    return block;
}

public void DataReceived(DataBlock data_block) {
    _Promise.TrySetResult(data_block);
}

Here's an executable example.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-29
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    相关资源
    最近更新 更多