我最近开始使用wpf。我有一个简单的TreeView和OnSelectedItemChanged事件:
private void Treeview1_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
Thread.Sleep(1000);
}
我得到的当前工作流程:
这是非常无响应的工作流程。我需要的是:
我能否以某种方式立即触发视觉点击选择?
答案 0 :(得分:0)
是的,你可以。
您所要做的就是不阻止UI线程,以便Dispatcher
可以选择TreeViewItem
。
最好的方法可能是在事件处理程序中使用async/await
如果您不使用MVVM并且需要直接操作UI元素,则可以执行以下操作:
private async void Treeview1_OnSelectedItemChanged(object sender,
RoutedPropertyChangedEventArgs<object> e)
{
// TreeViewItem gets selected immediately.
// Now let's do some background work, for example getting some data.
await Task.Run(() => DoSomeBackgroundWork());
// And fill the DataGrid with the results.
// Thanks to async/await we're already in the dispatcher thread again.
dataGrid.Items.Add(...);
}
private void DoSomeBackgroundWork()
{
// Simulate some blocking synchronous work.
Thread.Sleep(1000);
}
如果您使用MVVM进行数据绑定(我强烈推荐),那么您可能不需要在调度程序线程中填写ViewModel
的内容。
相反,您可以在async
上下文中执行此操作,只需告诉上面的await
,之后不需要上下文切换到调度程序线程:
await Task.Run(() => DoSomeBackgroundWork())
.ConfigureAwait(continueOnCapturedContext: false);
myViewModel.Items.Add(...);
但请注意,您很可能也必须应用某种形式的并发安全性,因为如果用户快速点击多个TreeViewItems
,则无法保证多个Task.Run()
赢得& #39; t相互干扰。
有许多方法可以确保并发安全性(从只存储在字段或属性中的简单易失性标志开始)但这样做太多了,只能在这一个答案中包含所有内容。
例如,您可以查看Stephen Cleary。他写了一些关于这个主题的非常精彩的文章
或者Stephen Toub与.NET中异步编程的实现密切相关。
作为一般建议,您应尽量在调度程序线程中尽量少做。只做只需要它的操作,比如直接修改UI元素。