В приложении WPF у меня есть класс, который получает сообщения по сети. Всякий раз, когда объект указанного класса получает полное сообщение, возникает событие. В MainWindow приложения у меня есть обработчик событий, подписанный на это событие. Обработчик событий гарантированно будет вызываться в потоке графического интерфейса приложения.
Всякий раз, когда вызывается обработчик событий, содержимое сообщения должно быть применено к модели. Это может быть довольно дорого ( > 200 мс на текущем оборудовании). Поэтому применение этого сообщения выгружается в пул потоков с помощью Task.Run.
Теперь сообщения могут быть получены с очень близкой последовательностью, поэтому обработчик события можно вызвать, пока предыдущее изменение все еще обрабатывается. Каков самый простой способ гарантировать, что сообщения применяются только по одному? До сих пор я придумал следующее:
using System;
using System.Threading.Tasks;
using System.Windows;
public partial class MainWindow : Window
{
private Model model = new Model();
private Task pending = Task.FromResult<bool>(false);
// Assume e carries a message received over the network.
private void OnMessageReceived(object sender, EventArgs e)
{
this.pending = ApplyToModel(e);
}
private async Task ApplyToModel(EventArgs e)
{
await this.pending;
await Task.Run(() => this.model.Apply(e)); // Assume this is an expensive call.
}
}
Кажется, что это работает так, как ожидалось, однако также кажется, что это неизбежно приведет к "утечке памяти", поскольку задача применения сообщения всегда будет всегда ждать выполнения задачи, которая применяла предыдущее сообщение. Если это так, то следующее изменение должно избегать утечки:
private async Task ApplyToModel(EventArgs e)
{
if (!this.pending.IsCompleted)
{
await this.pending;
}
await Task.Run(() => this.model.Apply(e));
}
Является ли это разумным способом избежать повторного размещения с обработчиками событий async void?
EDIT. Удалено ненужное выражение await this.pending;
в OnMessageReceived
.
EDIT 2: сообщения должны применяться к модели в том же порядке, в котором они были получены.