Я разрабатываю сетевое приложение, которое получает данные из веб-сокета, модифицирует их и загружает в службу данных. Загрузка данных занимает некоторое время, и я хотел бы скрыть эту задержку, загружая несколько сообщений одновременно. Когда загрузка завершена, мне нужно отправить подтверждение обратно через веб-сокет.
Я создал рабочую очередь для хранения всех невыполненных задач. Кажется, это работает хорошо, поэтому я не включил его. Но моя задача загрузки, кажется, заканчивается, прежде чем она на самом деле завершена. Вот сокращенный пример.
private async Task UploadDataAsync(string data, CancellationToken cancellationToken)
{
Task uploadTask = new Task(async () =>
{
// Simulates uploading data
await Task.Delay(5000, cancellationToken);
});
_ = uploadTask.ContinueWith(async (t1) =>
{
// Clean up the task
await RemoveTask(t1);
if (t1.IsCompletedSuccessfully)
await SendAck(this, data, cancellationToken);
else if (t1.IsFaulted)
logger.LogError(t1.Exception, $"An error occurred while uploading {data}");
else if (t1.IsCanceled)
logger.LogWarning($"An upload task {data} was canceled");
}, TaskScheduler.Default);
await AddTask(uploadTask);
uploadTask.Start();
}
В предыдущем коде подтверждение отправляется до загрузки данных. Удивительно, но это потому, что в моей Задаче используется асинхронная лямбда c По причине, которую я не понимаю, uploadTask
завершается, когда ожидается загрузка. Поэтому я изменил это на что-то вроде этого:
private async Task UploadDataAsync(string data, CancellationToken cancellationToken)
{
Task uploadTask = new Task(() =>
{
// Simulates uploading data
Task.Delay(5000, cancellationToken).Wait();
});
_ = uploadTask.ContinueWith((t1) =>
{
// Clean up the task
RemoveTask(t1).Wait();
if (t1.IsCompletedSuccessfully)
SendAck(this, data, cancellationToken).Wait();
else if (t1.IsFaulted)
logger.LogError(t1.Exception, $"An error occurred while uploading {data}");
else if (t1.IsCanceled)
logger.LogWarning($"An upload task {data} was canceled");
}, TaskScheduler.Default);
await AddTask(uploadTask);
uploadTask.Start();
}
Теперь все выполняется в правильном порядке, за исключением случаев, когда что-то не так go или операция отменена (например, сервер выключен). Теперь я имею дело с AggregateExceptions и TaskCanceledExceptions.
Кажется, это должно быть проще, чем я это делаю. Я делаю это неправильно?
Редактировать Добавление псевдокода, который вызывает UploadDataAsync
для контекста.
protected override async Task DoConnection(CancellationToken cancellationToken)
{
while (_websocket.State == WebSocketState.Open && !cancellationToken.IsCancellationRequested)
{
// Simulates getting websocket data
string result = await _websocket.ReceiveAsync();
// This should only asynchronously wait for the upload task to get
// created. It should not wait for the upload to complete.
await OnDataReceived(result, cancellationToken);
}
}