如何 return 等待调度程序线程中的事件的可等待(任务?)
How to return awaitable (Task?) that waits for an event in Dispatcher Thread
我有话题:
- UI 具有 Dispatcher 循环的线程
- 在队列框架中侦听消息的后台线程。
收到消息后,后台线程中会触发一个事件:
messageReceiver.Received += (sender, args) => ...
在 UI 线程中,我想等待一条消息,如下所示:
void ButtonClicked(object sender, RoutedEventArgs e) {
await NextMessage(); //should return when messageReceiver.Received is fired
}
如何实现可等待的NextMessage方法,使其不会每次都创建新线程?
有 SemaphoreSlim
class 我可以等待 WaitAsync,但似乎创建了新线程,该线程在释放 SemaphoreSlim 之前一直处于阻塞状态。
也许 TaskCompletionSource
是正确的选择?那我应该使用哪个 TaskCreationOption?
您提到了 TaskCompletionSource
,我相信这正是您在这里需要的。您可以像这样将它绑定到 .Received
事件:
static Task<IEnumerable<Message>> FromEvent(Receiver messageReceiver)
{
var tcs = new TaskCompletionSource<IEnumerable<Message>>();
EventHandler<IEnumerable<Message>> handler = null;
handler = (o, e) =>
{
messageReceiver.Received -= handler;
tcs.SetResult(e.Messages);
};
messageReceiver.Received += handler;
return tcs.Task;
}
那么你可以这样等待:
// Having the async keyword is fine here since this is an event handler
async void ButtonClicked(object sender, RoutedEventArgs e)
{
var messages = await FromEvent(messageReceiver);
}
我有话题:
- UI 具有 Dispatcher 循环的线程
- 在队列框架中侦听消息的后台线程。
收到消息后,后台线程中会触发一个事件:
messageReceiver.Received += (sender, args) => ...
在 UI 线程中,我想等待一条消息,如下所示:
void ButtonClicked(object sender, RoutedEventArgs e) {
await NextMessage(); //should return when messageReceiver.Received is fired
}
如何实现可等待的NextMessage方法,使其不会每次都创建新线程?
有 SemaphoreSlim
class 我可以等待 WaitAsync,但似乎创建了新线程,该线程在释放 SemaphoreSlim 之前一直处于阻塞状态。
也许 TaskCompletionSource
是正确的选择?那我应该使用哪个 TaskCreationOption?
您提到了 TaskCompletionSource
,我相信这正是您在这里需要的。您可以像这样将它绑定到 .Received
事件:
static Task<IEnumerable<Message>> FromEvent(Receiver messageReceiver)
{
var tcs = new TaskCompletionSource<IEnumerable<Message>>();
EventHandler<IEnumerable<Message>> handler = null;
handler = (o, e) =>
{
messageReceiver.Received -= handler;
tcs.SetResult(e.Messages);
};
messageReceiver.Received += handler;
return tcs.Task;
}
那么你可以这样等待:
// Having the async keyword is fine here since this is an event handler
async void ButtonClicked(object sender, RoutedEventArgs e)
{
var messages = await FromEvent(messageReceiver);
}