强制异步等待IProgress<;T>;.要同步的Report()
本文关键字:同步 Report gt IProgress 等待 lt 异步 | 更新日期: 2023-09-27 18:25:27
对于一些长任务,我使用基于任务的异步模式(TAP),使用IProgress<T>
向主UI报告进度。Progress.Report
似乎只有在前面有另一个等待任务时才起作用。例如,如果我在内联for循环中使用,则报告消息仅在任务结束时发布:
public async Task<bool> DoSomething(IProgress<string> progress)
{
progress.Report("Start"); // works
await SomeTask();
progress.Report("Message 1"); // works ONLY at end
for ()
{
progress.Report("Message x"); // works ONLY at end
// do some tasks inline
}
return true;
}
是否有某种方法可以强制同步发布报表消息?谢谢
进度报告似乎只有在前面有另一个等待任务的情况下才有效。
这是有道理的。Progress<T>
捕获SynchronizationContext
,并在调用Report
方法后向其发布。如果你是async,那么方法并不是真正的异步,并且大部分CPU工作都在UI线程上完成,那么你就不会释放消息循环来处理更多的事件,因此你只会看到它在方法调用结束时更新。
Progress<T>.Report
就是这样实现的:
protected virtual void OnReport(T value)
{
// If there's no handler, don't bother going through the [....] context.
// Inside the callback, we'll need to check again, in case
// an event handler is removed between now and then.
Action<T> handler = m_handler;
EventHandler<T> changedEvent = ProgressChanged;
if (handler != null || changedEvent != null)
{
// Post the processing to the [....] context.
// (If T is a value type, it will get boxed here.)
m_synchronizationContext.Post(m_invokeHandlers, value);
}
}
为了保持响应,您可以将for
循环卸载到线程池线程:
public async Task<bool> DoSomethingAsync(IProgress<string> progress)
{
progress.Report("Start"); // works
await SomeTask();
progress.Report("Message 1");
await Task.Run(() =>
{
progress.Report("Message x");
// Do more CPU bound work
}
return true;
}