C# 强制异步等待IProgress<;T>;。要同步的报表()

C# 强制异步等待IProgress<;T>;。要同步的报表(),c#,.net,async-await,C#,.net,Async Await,我正在使用基于任务的异步模式(TAP)执行一些长任务,使用IProgress向主UI报告进度。 Progress.Report似乎只有在前面有另一个等待任务时才起作用。 例如,如果在内联for循环中使用,则报告消息仅在任务结束时发布: public async Task<bool> DoSomething(IProgress<string> progress) { progress.Report("Start"); // works await Some

我正在使用基于任务的异步模式(TAP)执行一些长任务,使用
IProgress
向主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;
}
公共异步任务DoSomething(IProgress progress)
{
progress.Report(“Start”);//有效
等待某项任务();
progress.Report(“Message 1”);//只在末尾起作用
对于()
{
progress.Report(“Message x”);//只在末尾起作用
//在线执行一些任务
}
返回true;
}
有没有办法强制同步发布报告消息? 谢谢

只有在前面有另一个等待任务的情况下,Progress.Report似乎才起作用

这是有道理的<代码>进度捕获
同步上下文
并在调用
报告
方法后发布到该上下文。如果您是异步的,那么这个方法并不是真正的异步的,并且大部分CPU工作都是在UI线程上完成的,那么您并没有释放消息循环来处理更多的事件,因此您只看到它在方法调用结束时更新

这就是进度报告的实现方式:

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);
        }
}

“仅在结束时工作”是什么意思?如果您希望
SomeTask
报告进度,那么它应该有一个
IProgress
参数,并通过
progress正常报告进度。报告
,因此我需要调用for循环来报告其他等待任务?@kim您需要释放UI线程以允许其更新。如果您实际上没有任何异步工作要做,您可以使用
任务在线程池线程上执行其他CPU限制的工作。运行
,这样您就不会冻结
for
循环为非阻塞的UIT了?谢谢。任务。运行是解决方案。
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;
}