2

У меня есть темы:Как вернуть awaitable (Task?), Что ждет события в Диспетчерской Теме

  1. UI нить с диспетчерской петлей
  2. фонового поток, который прослушивает сообщения в рамках массового обслуживания.

при получении сообщения, событие вызывается в фоновом потоке:

messageReceiver.Received += (sender, args) => ... 

В UI потоке я хотел бы, чтобы ждать сообщение, что-то вроде этого:

void ButtonClicked(object sender, RoutedEventArgs e) { 
    await NextMessage(); //should return when messageReceiver.Received is fired 
} 

Как реализовать ожидаемый метод NextMessage, поэтому он не создает новый поток каждый раз?

Класс SemaphoreSlim, где я могу подождать WaitAsync, но создается новый поток, который блокируется до тех пор, пока не будет выпущен SemaphoreSlim.

Возможно, TaskCompletionSource - это путь? Какую TaskCreationOption следует использовать?

+0

'SemaphoreSlim' не создает поток. –

+0

Так в чем же разница между 'СемафорСлим.WaitAsync' и' TaskCompletionSource.Task'? – Liero

+0

'TaskCompletionSource' - одноразовое уведомление. 'СемафорСлим' можно использовать повторно. Существуют и другие различия, но это наиболее применимо к этой дискуссии. –

ответ

1

Вы упомянули 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); 
} 
+0

btw, это создает утечку памяти, не так ли? – Liero

+0

Я добавил очистку –

+0

Я закончил использовать RX: 'await ObservableFromReceivedEvent (messageReceiver) .FirstAsync (e => e.MessageId == this.MessageId)' – Liero

Смежные вопросы