Chr*_*ris 5 c# wpf multithreading task mvvm
我们有一个根据MVVM模式构建的应用程序.在不同的时间,我们启动任务以转到数据库以检索数据,然后我们填充一个ObservableCollection,WPF控件与该数据绑定到该ObservableCollection.
我们有点困惑,当我们在任务线程而不是UI线程上填充ObservableCollection时,UI仍然正在更新/正常运行.我们期待一个错误,并且必须更改代码以填充UI线程上的集合.
这是一个危险的场景吗?我们应该填充UI线程吗?
获取数据的代码:
Task.Factory.StartNew(() =>
UiDataProvider.RefreshForwardContractReport(fcrIdField.Value)
)
.ContinueWith(task => {
if (task.Result.OperationSuccess)
{
// This updates the ObseravableCollection, should it be run on UI thread??
RefreshReport(task.Result.OperationResult);
}
});
Run Code Online (Sandbox Code Playgroud)
WPF 在每个版本中都允许更多的跨线程操作。其他 MVVM 平台根本不允许它们。在 的情况下ObservableCollection,除非您正在使用 ,否则EnableCollectionSynchronization从后台线程更新是不正确的。
我同意 @avo 的观点,因为您应该将 ViewModel(您的逻辑UI)视为具有 UI 线程关联性(如文字UI)。所有数据绑定更新都应在 UI 上下文中完成。
正如@Cameron 指出的,这最容易通过async:
var result = await Task.Run(
() => UiDataProvider.RefreshForwardContractReport(fcrIdField.Value));
if (result.OperationSuccess)
{
RefreshReport(result.OperationResult);
}
Run Code Online (Sandbox Code Playgroud)
延续在 UI 线程上运行的原因可能有多种。MVVM 框架可能会有所帮助,或者有其他东西让它在 UI 线程上运行,或者你只是运气好。
为了确保延续在 UI 线程上运行,您可以TaskScheduler像这样捕获之前的 UI。
var uiScheduler = TaskScheduler.FromCurrentSyncronizationContext();
Task.Factory.StartNew(() =>
UiDataProvider.RefreshForwardContractReport(fcrIdField.Value),
TaskCreationOptions.LongRunning
) // Ensures the task runs in a new thread
.ContinueWith(task => {
if (task.Result.OperationSuccess)
{
RefreshReport(task.Result.OperationResult);
}
}, uiScheduler); // Runs the continuation on the UI thread.
Run Code Online (Sandbox Code Playgroud)
这假设外部方法首先从 UI 运行。否则,您可以在顶层捕获 UI 调度程序并在应用程序中全局访问它。
如果你可以使用 async/await 那么代码就会变得更容易。
var result = await Task.Factory.StartNew(
() => UiDataProvider.RefreshForwardContractReport(fcrIdField.Value),
TaskCreationOptions.LongRunning
);
if (result.OperationSuccess)
{
RefreshReport(result.OperationResult);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10758 次 |
| 最近记录: |