Ale*_*and 23 c# asynchronous progress
此代码段来自Stephen Cleary的博客,并提供了使用Task.Run时如何报告进度的示例.我想知道为什么没有更新UI的交叉线程问题,我的意思是为什么不需要调用?
private async void button2_Click(object sender, EventArgs e)
{
var progressHandler = new Progress<string>(value =>
{
label2.Text = value;
});
var progress = progressHandler as IProgress<string>;
await Task.Run(() =>
{
for (int i = 0; i != 100; ++i)
{
if (progress != null)
progress.Report("Stage " + i);
Thread.Sleep(100);
}
});
label2.Text = "Completed.";
}
Run Code Online (Sandbox Code Playgroud)
Gus*_*dor 28
Progress<T>在SynchronisationContext实例化时捕获电流.无论何时打电话Report,它都会秘密地将其委托给捕获的上下文.在该示例中,捕获的上下文是UI,意味着不会发生异常.
Jea*_*nal 11
该Progress<T>构造函数捕获当前SynchronizationContext对象.
该SynchronizationContext班是一个设备抽象所涉及的线程模型的细节.也就是说,在Windows Forms中它将使用Control.Invoke,在WPF中它将使用Dispatcher.Invoke,等等.
当progress.Report对象被调用时,Progress对象本身知道它应该使用捕获运行其委托SynchronizationContext.
换句话说,它的工作原理是因为Progress设计用于处理这种情况而开发人员不必明确说出来.
看起来你很困惑,因为这个跨线程机器的一部分是隐藏在开发人员眼中的,所以你只需要"接受和使用":http://blogs.msdn.com/b/dotnet/archive/2012 /06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-apis.aspx
我们引入了IProgress界面,使您能够创建显示进度的体验.此接口公开Report(T)方法,异步任务调用该方法来报告进度.您在async方法的签名中公开此接口,并且调用方必须提供实现此接口的对象.任务和调用者一起创建了一个非常有用的链接(并且可以在不同的线程上运行).
我们还提供了Progress类,它是IProgress的一个实现.我们鼓励您在实现中使用Progress,因为它处理有关保存和恢复同步上下文的所有簿记.Progress公开事件和Action回调,在任务报告进度时调用它们.通过此模式,您可以编写代码,以便在进度发生变化时立即做出反应.IProgress和Progress共同提供了一种将进度信息从后台任务传递到UI线程的简便方法.
还有一件事需要提及:在完成工作的一部分之后,将调用进度通知,而不仅仅是在那一刻.因此,如果您的UI线程处于空闲状态且您有备用CPU核心,则延迟将几乎为零.如果您的UI线程忙,则在UI线程恢复空闲之前不会调用通知(无论您的计算机有多少备用CPU核心).
| 归档时间: |
|
| 查看次数: |
25098 次 |
| 最近记录: |