SOf*_*tic 5 c# wpf mvvm task-parallel-library tpl-dataflow
我在遵循MVVM模式的WPF应用程序中使用TPL数据流.我有一个TransformBlock<object,object>和ActionBlock<object>我一样,我将它们连接起来:
transformBlock.LinkTo(notificationBlock);
Run Code Online (Sandbox Code Playgroud)
本ActionBlock<object>应更新我对当前进度视图的进度条,但UI似乎被冻结,只有当一切都完成处理更新.
我的CurrentProgress财产看起来像这样:
private double _CurrentProgress;
public double CurrentProgress
{
get { return _CurrentProgress; }
set
{
_CurrentProgress = value;
RaisePropertyChanged("CurrentProgress");
}
}
Run Code Online (Sandbox Code Playgroud)
并且我将它绑定到我的View,就像这样:
<ProgressBar Value="{Binding CurrentProgress, Mode=OneWay}" Name="uxProgressBar"/>
Run Code Online (Sandbox Code Playgroud)
我错过了什么吗?为什么TPL会阻止UI线程?
编辑
这就是我实例化TPL的方式:
foreach(var myObj in ObjList)
{
transformBlock.Post(myObj);
}
Run Code Online (Sandbox Code Playgroud)
变换块:
TransformBlock<object, object>(
temp =>
{
var response = ProcessRecord(temp);
return response.Status;
},
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism =20
});
Run Code Online (Sandbox Code Playgroud)
行动阻止:
ActionBlock<object>(
temp =>
{
CurrentProgress = (double)temp.RecordNumber/(double)TotalRecords;
},
new ExecutionDataflowBlockOptions
{
TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
});
Run Code Online (Sandbox Code Playgroud)
UPDATE
正在调用的Web服务是TransformBlock遗留(asmx)Web服务,并且未被调用Async.解决此问题后,其他一切工作正常,而不使用Dispatcher或任何其他建议的解决方案.
从其中一个评论到问题,似乎WPF确实支持从另一个线程发布到UI线程.我找不到任何关于此的官方文档.
首先,您ActionBlock不必CurrentProgress直接更改属性。
原因是该RaisePropertyChanged函数将直接运行ProgressBar对象的代码。这是不允许的,因为它是 UIThread 拥有的对象。
在他自己的线程中运行ActionBlock,他需要将进度条更新顺序发布到 UI 线程(通过使用)Dispatcher.BeginInvoke:
ActionBlock<object>(
temp =>
{
double progress = (double)temp.RecordNumber/(double)TotalRecords;
Dispatcher.BeginInvoke((Action)(() =>
{
CurrentProgress = progress;
}));
},
new ExecutionDataflowBlockOptions
{
TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
});
Run Code Online (Sandbox Code Playgroud)
为了做出你想要的东西,你必须首先改变这一点。
其次(如果这不会改变任何事情),您必须检查您的 UI 线程是否正在等待TransformBlock. 如果您的ICommand(例如,如果您从按钮调用它)不是异步的,请执行以下操作:
transformBlock.Completion.Wait();
Run Code Online (Sandbox Code Playgroud)
不行。因为你的UIThread会等待你的处理结束并且不会接受之前的progressBar更新命令直到结束。
祝你好运 !如果它始终不起作用,请发布新的详细信息。
| 归档时间: |
|
| 查看次数: |
2036 次 |
| 最近记录: |