问题
I have threads:
- UI thread with Dispatcher loop
- background thread that listens for messages in a queuing framework.
when a message is received, an event is fired in the background thread:
messageReceiver.Received += (sender, args) => ...
In UI thread I would like to await a message, something like this:
void ButtonClicked(object sender, RoutedEventArgs e) {
await NextMessage(); //should return when messageReceiver.Received is fired
}
How to implement awaitable NextMessage method, so it does not create new thread each time?
There is SemaphoreSlim
class where I can await WaitAsync, but is seems to create new thread that is blocked until SemaphoreSlim is released.
Maybe TaskCompletionSource
is the way to go? Which TaskCreationOption should I use then?
回答1:
You mentioned the TaskCompletionSource
and that is what I believe you need here. You'd tether it to the .Received
event like so:
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;
}
Then you could await it like this:
// 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);
}
来源:https://stackoverflow.com/questions/38565478/how-to-return-awaitable-task-that-waits-for-an-event-in-dispatcher-thread