1

我想要做什么: 我在 WPF(c#) 中使用 Web 服务 DLL。DLL 包含一个 Web 服务,您可以在我的代码中将其视为SmsSender类。调用这个类的每个方法都很耗时,所以我需要在其他线程中运行它的方法。

我做什么: 我将 DataView 对象(即方法的“返回值”)设置为 DataGrid 的 ItemsSource。所以我用Dispatcher.BeginInvoke().

我的问题: 我的问题是使用Dispatcher.BeginInvoke()可以冻结我的程序,即使我在不​​同的线程中运行它。我想在不冻结的情况下调用方法。是否可以定义超时?

更新1:

如何将 DataView 从耗时的方法设置为 DataGrid?

我的代码:

Action action = () =>
{
    SmsSender sms = new SmsSender();

    dgUser1.ItemsSource = sms.GetAllInboxMessagesDataSet().Tables[0].DefaultView;
};

dgUser1.Dispatcher.BeginInvoke(action);

提前致谢

4

2 回答 2

2

这很容易。你永远不应该在你的 UI 线程上阻塞 I/O。

SmsSender sms = new SmsSender();
DataView result = sms.GetAllInboxMessagesDataSet().Tables[0].DefaultView
Action action = () =>
{
    dgUser1.ItemsSource = result;
};
dgUser1.Dispatcher.BeginInvoke(action);

然而,这实际上不是您应该编写 WPF 应用程序的方式。这种模式是使用 WinForms 之类的模式来完成的。您真的应该使用 DataBinding。

数据绑定会处理你所有的Dispatcher调用。

于 2013-11-02T22:36:09.193 回答
1

Dispatcher.BeginInvoke在 UI 线程上运行委托,并且由于您已经在调度程序上执行了完整的操作,它将在 UI 线程上执行,这会导致 UI 挂起问题。

有很多方法可以将耗时的操作委托给后台线程并在 UI 线程上调度 UI 调用。

简单的例子是使用BackgroundWorker. 将非 UI 内容放在DoWork事件处理程序中,并将 UI 操作放在RunWorkerCompleted仅在 UI 线程上调用的处理程序上,因此需要将调用调度到 UI 调度程序。

小样本 -

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork+=new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted +=
        new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
   dgUser1.ItemsSource = (DataView)e.Result;
}        

void worker_DoWork(object sender, DoWorkEventArgs e)
{
   SmsSender sms = new SmsSender();
   e.Result = sms.GetAllInboxMessagesDataSet().Tables[0].DefaultView;
}
于 2013-11-03T09:08:34.717 回答