调用component时的程序冻结.Dispatcher.BeginInvoke()

时间:2013-11-02 22:11:41

标签: c# wpf dispatcher ui-thread

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

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

我的问题:  我的问题是使用Dispatcher.BeginInvoke()即使我在另一个线程中运行它也可以冻结我的程序。我想调用方法而不冻结。是否可以定义超时?

UPDATE1:

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

我的代码:

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

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

dgUser1.Dispatcher.BeginInvoke(action);

提前致谢

2 个答案:

答案 0 :(得分: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次来电。

答案 1 :(得分:1)

Dispatcher.BeginInvoke在UI线程上运行委托,并且由于您已对调度程序执行完整操作,因此它将在UI线程上执行,从而导致UI挂起问题。

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

简单的例子是使用BackgroundWorker。将非UI内容放在DoWork事件处理程序和UI操作上的RunWorkerCompleted处理程序上,只在UI线程上调用,因此需要将调用分派给UI disptacher。

小样本 -

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;
}