Как получить статус длительно выполняемой задачи

#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 , если вы хотите более сложное обновление.