Вашего метод отмечен async Task
, поэтому компилятор ожидает, что он ничего не вернет. Если вы хотите вернуть задачу, то вы не должны отмечать метод async
. Кроме того, вы можете использовать await
внутри метода async
.
// Option 1
Task Foo (Action<int> onProgressPercentChanged)
{
return Task.Run (() =>
{
for (int i = 0; i < 1000; i++)
{
if (i % 10 == 0) onProgressPercentChanged (i/10);
}
});
}
// Option 2
async Task Foo (Action<int> onProgressPercentChanged)
{
await Task.Run (() =>
{
for (int i = 0; i < 1000; i++)
{
if (i % 10 == 0) onProgressPercentChanged (i/10);
}
});
}
Более подробную информацию о разнице между этими двумя, см мой пост в блоге на eliding async.
к другим проблемам ...
Использование отчетности, встроенных в .NET, а не свертывать свой собственный прогресс.
.NET использует IProgress<T>
тип, так что вы можете использовать это:
Следуя конвенции прогресса, мы позволяем звонящие к не запросу прогресс обновления, и мы также позволяют очень естественно сортировочная в потоке пользовательского интерфейса с использованием Progress<T>
:
// Caller, from UI thread
var progress = new Progress<int>(report =>
{
// Handle progress report. This code is already on the UI thread! :)
});
await Foo(progress);
не используйте Task.Run
в реализации; используйте метод Task.Run
для вызова метода.Using Task.Run
to implement fake-asynchronous methods is an antipattern. Я также пишу об этом on my blog.
Применяя это исправление делает Foo
синхронные, который совсем правильно, так как он не делает никакого фактического асинхронной работы:
void Foo(IProgress<int> progress = null)
{
for (int i = 0; i < 1000; i++)
{
if (progress != null && i % 10 == 0) progress.Report(i/10);
}
}
// Caller
var progress = new Progress<int>(report => ...);
await Task.Run(() => Foo(progress));
И, наконец, не дроссельных отчеты о ходе работы на источнике; дросселируйте их на приемнике. Если ваш код когда-либо работает на разных процессорах, то любое дросселирование, которое вы выполняете в источнике (i % 10
), будет проблематичным.Лучше использовать реализацию IProgress<T>
, которая дросселирует.
Это хорошо упрощает код:
void Foo(IProgress<int> progress = null)
{
for (int i = 0; i < 1000; i++)
{
if (progress != null) progress.Report(i/10);
}
}
Спасибо, tdragon, попробовал, и это сработало. Обычно, когда код, который не будет компилироваться, иллюстрируется в книге, указывается, что он не будет. На этот раз это не так. – AndrewH