#c# #asynchronous #async-await #task
#c# #асинхронный #асинхронный-ожидание #задача
Вопрос:
Почему Status
мой Task
возврат «WaitingForActivasion» вместо «Running»?
Если я удаляю Task.Run
, я застреваю в while
цикле, поэтому я предполагаю, что он не работает асинхронно.
public class StateManagerTest
{
[Fact]
public void Start_TaskStatus()
{
StateManager manager = new StateManager();
manager.Start();
Assert.True(manager.Status == System.Threading.Tasks.TaskStatus.Running.ToString());
}
}
public class StateManager
{
private CancellationTokenSource cts = new();
private Task updateTask;
public HashSet<StateItem> StateItems { get; private set; }
public Provider Provider { get; private set; }
public List<OutputService> OutputServices { get; private set; }
public string Status
{
get => updateTask.Status.ToString();
}
public StateManager()
{
StateItems = new();
OutputServices = new();
Provider = new();
}
public void Stop()
{
cts.Cancel();
}
public void Start()
{
updateTask = Task.Run(() => Update(cts.Token))
.ContinueWith(t => Debug.WriteLine(t.Exception.Message), TaskContinuationOptions.OnlyOnFaulted);
}
private async Task Update(CancellationToken token)
{
while (true)
{
// get changes from outputs
Dictionary<StateItem, object> changes = new Dictionary<StateItem, object>();
foreach (var service in OutputServices)
{
var outputChanges = await service.GetChanges();
foreach (var change in outputChanges)
changes.TryAdd(change.Key, change.Value);
}
// write changes to provider source
await Provider.PushChanges(changes);
// update state
await Provider.UpdateStateItems();
// update all services
foreach (var service in OutputServices)
await service.UpdateSource();
if (token.IsCancellationRequested)
return;
}
}
}
Комментарии:
1. devblogs.microsoft.com/pfxteam/the-meaning-of-taskstatus
2. @TheGeneral Спасибо за информацию. Но выполняется ли цикл while в Update() по-прежнему? Или что-то не так с моим методом Start()?
3. «Но цикл while в Update() все еще выполняется» — да, хорошо, пока его нет… Но я думаю, что более широкий вопрос заключается в том, чего вы на самом деле пытаетесь достичь здесь?
4.
Task.Run
С асинхронной лямбдой (или с лямбдой, которая возвращаетTask
like в вашем случае) создает задачу в стиле promise. Задачи в стиле Promise никогда не переходят вRunning
состояние. Вы можете посмотреть здесь для получения более подробной информации: Обзор задачи, часть 3: Статус5. @TheodorZoulias даже без Task.Run он все равно будет ждать активации
Ответ №1:
Как отмечали другие, WaitingForActivation
это правильное состояние для задачи обещания, которая еще не завершена. В общем, я рекомендую не использовать Task.Status
или ContinueWith
; они являются реликвиями с того времени, когда async
они существовали / await
существовали.
Как получить статус длительно выполняемой задачи
Я полагаю, вы хотели бы получить отчет о ходе выполнения, который делается самостоятельно. Вход T
IProgress<T>
может быть a string
, если вы хотите простое текстовое обновление, или a double
, если вы хотите процентное обновление, или пользовательским struct
, если вы хотите более сложное обновление.