我正在使用基于任务的异步模式(TAP)执行一些长任务,使用IProgress<T>
向主UI报告进度。
Progress.Report
似乎仅在其前面有另一个等待任务时才起作用。
例如,如果我在内联循环中使用,则报告消息仅在任务结束时发布:
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;
}
是否有某种方法可以强制同步发布报告消息? 感谢。
答案 0 :(得分:3)
Progress.Report似乎只在前面有另一个await任务时才有效。
这是有道理的。 Progress<T>
抓取SynchronizationContext
并在您调用Report
方法后发布到其中。如果您的异步方法不是非同步并且主要是在UI线程上完成的CPU工作,那么您不会释放消息循环来处理更多事件,因此您只需要看到它在方法调用结束时更新。
这就是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;
}