我在遵循MVVM模式的WPF应用程序中使用TPL数据流。
我有一个TransformBlock<object,object>
和一个ActionBlock<object>
,我将它们连接起来:
transformBlock.LinkTo(notificationBlock);
ActionBlock<object>
应该使用当前进度更新视图中的进度条,但是UI似乎被冻结,只有在所有内容完成处理时才会更新。
我的CurrentProgress
属性如下所示:
private double _CurrentProgress;
public double CurrentProgress
{
get { return _CurrentProgress; }
set
{
_CurrentProgress = value;
RaisePropertyChanged("CurrentProgress");
}
}
我将它绑定到我的View就像这样:
<ProgressBar Value="{Binding CurrentProgress, Mode=OneWay}" Name="uxProgressBar"/>
我错过了什么吗?为什么TPL会阻止UI线程?
修改
这就是我实例化TPL的方式:
foreach(var myObj in ObjList)
{
transformBlock.Post(myObj);
}
变换块:
TransformBlock<object, object>(
temp =>
{
var response = ProcessRecord(temp);
return response.Status;
},
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism =20
});
行动阻止:
ActionBlock<object>(
temp =>
{
CurrentProgress = (double)temp.RecordNumber/(double)TotalRecords;
},
new ExecutionDataflowBlockOptions
{
TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
});
更新
在TransformBlock
中调用的Web服务是遗留(asmx)Web服务,并且它不会被称为Async
。解决此问题后,其他一切工作正常,而不使用Dispatcher
或任何其他建议的解决方案。
从其中一条评论到问题,似乎WPF确实支持从另一个线程发布到UI线程。虽然我还没有找到任何关于此的官方文档。
答案 0 :(得分:2)
首先,您的ActionBlock
不必直接更改CurrentProgress
媒体资源。
原因是RaisePropertyChanged
函数将直接运行ProgressBar
对象的代码。
这是不允许的,因为它是UIThread拥有的对象。
ActionBlock
在他自己的线程中运行,他需要将progressBar更新顺序发布到UI线程(使用Dispatcher.BeginInvoke
):
ActionBlock<object>(
temp =>
{
double progress = (double)temp.RecordNumber/(double)TotalRecords;
Dispatcher.BeginInvoke((Action)(() =>
{
CurrentProgress = progress;
}));
},
new ExecutionDataflowBlockOptions
{
TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
});
为了制作你想要的东西,你必须首先改变这一点。
其次(如果这不会改变任何内容),您必须检查您的UI线程是否在等待TransformBlock
的完成。如果你的ICommand
(如果你从一个按钮中调用它来作为例子)不是ASync并且做这样的事情:
transformBlock.Completion.Wait();
不行。因为您的UIThread将等待您的治疗结束,并且不会将之前的progressBar更新订单直到结束。
祝你好运! 如果新细节不起作用,请发布。答案 1 :(得分:1)
尝试使用&#39; SendAsync&#39;
将代码发布到TransformBlockforeach(var myObj in ObjList)
{
await transformBlock.SendAsync(myObj);
}
答案 2 :(得分:1)
您应该使用Dispatcher
通知UI线程您要从后台进程更新绑定值。
以下是文章的链接:
http://msdn.microsoft.com/en-us/magazine/cc163328.aspx
http://msdn.microsoft.com/en-us/library/vstudio/system.windows.threading.dispatcher
我将整理一个类似的代码示例并很快更新此响应。