C # await Task.Run не ожидается - PullRequest
0 голосов
/ 04 июня 2019

У меня есть какая-то длительная фоновая задача расчета

private async void StartButton_onClick(object sender, RoutedEventArgs e)
{
    cts = new CancellationTokenSource();
    var task = Task.Run(() => Calculate(cts.Token));
    tasks.Add(task);
    await task;
    tasks.Remove(task);
    cts = null;
}

Эта задача может быть отменена, когда пользователь нажимает кнопку Cancel, и должна автоматически отменяться, когда пользователь вызывает какую-либо другую деятельность, скажем, нажимает Change кнопка, чтобы открыть диалоговое окно для изменения параметров расчета.

Чтобы избежать записи кода отмены дважды для двух операций, я переместил его в отдельный метод

public async void CancelAsync()
{
    if (cts != null && !cts.IsCancellationRequested)
    {
        cts.Cancel();
        await Task.WhenAll(tasks);
    }
}

и вызвал его изсобытие нажатия кнопки

private async void CancelButton_onClick(object sender, RoutedEventArgs e)
{
    await Task.Run(() => CancelAsync());
}

private async void ChangeButton_onClick(object sender, RoutedEventArgs e)
{
    await Task.Run(() => CancelAsync());
    OpenDialog();
}

Проблема в том, что метод OpenDialog() вызывается до того, как CancelAsync() запускается в соревнование.

В чем я тут не прав?пожалуйста

Ответы [ 2 ]

3 голосов
/ 04 июня 2019

Поскольку вы вызываете метод CancelAsync () из лямбды, которая не является асинхронной и не ожидается, лямбда завершится до возврата метода CancelAsync(). Чтобы заставить его работать по назначению, используйте либо

public async Task CancelAsync()
{
    if (cts != null && !cts.IsCancellationRequested)
    {
        cts.Cancel();
        await Task.WhenAll(tasks);
    }
}

await CancelAsync();
1 голос
/ 04 июня 2019

Проблема заключается в использовании Task.Run, который предназначен для запуска некоторого синхронного кода в пуле потоков и позволяет вам ожидать результата этого.Однако вы передаете асинхронный код в Task.Run, как если бы он был синхронным кодом, поэтому Task.Run считает, что работа завершена, как только CancelAsync () возвращает задачу, а не когда она завершает свою задачу.

Попробуйте вместо этого:

private async void ChangeButton_onClick(object sender, RoutedEventArgs e)
{
    await CancelAsync();
    OpenDialog();
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...