我想从WPF(c#)中的多个线程更新我的DataGrid。我使用 dataGrid.Dispatcher.BeginInvoke() 和 dataGrid.Dispatcher.Invoke(),但它们冻结了程序(主线程)。如何从多个线程更新超时的数据网格(因为我使用的Web服务可能无法访问)。
使用Task
异步启动 Web 服务请求。为此,您可能需要将 EAP(基于事件的异步模式)样式转换为 TAP(基于任务的异步模式)样式。这是你如何做到这一点。
private Task<IEnumerable<YourDataItem>> CallWebServiceAsync()
{
var tcs = new TaskCompletionSource();
var service = new YourServiceClient();
service.SomeOperationCompleted +=
(sender, args) =>
{
if (args.Error == null)
{
tcs.SetResult(args.Result);
}
else
{
tcs.SetException(args.Error);
}
};
service.SomeOperationAsync();
return tcs.Task;
}
完成此操作后,可以使用新的async
和await
关键字进行调用,并使用延续样式语义等待它返回。它看起来像这样。
private async void Page_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
IEnumerable<YourDataItem> data = await CallWebServiceAsync();
YourDataGrid.DataSource = data;
}
就是这样!没有比这更优雅的了。这将在后台线程上异步执行操作,然后将结果绑定到 UI 线程上的DataGrid
。
如果无法访问 WCF 服务,则它将引发异常,并将附加到Task
,以便向上传播到await
调用。此时,它将被注入到执行中,并在必要时用try-catch
包裹。
如果不需要在线程中完成 DataGrid 编辑,则可以在主线程中运行它们,如下所示:
this.Invoke((Action)delegate
{
//Edit the DataGrid however you like in here
});
确保只把你需要运行的东西放在主线程中(否则会破坏多线程的目的)。