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

C# 调用component.Dispatcher.BeginInvoke()时程序冻结,c#,wpf,dispatcher,ui-thread,C#,Wpf,Dispatcher,Ui Thread,我想做什么: 我正在WPF(c#)中使用web服务DLL。DLL包含一个web服务,您可以在我的代码中将其作为SmsSenderclass查看。调用这个类的每个方法都很耗时,所以我需要在其他线程中运行它的方法 我的工作: 我将DataView对象(即方法的“返回值”)设置为DataGrid的ItemsSource。所以我使用了Dispatcher.BeginInvoke() 我的问题: 我的问题是使用Dispatcher.BeginInvoke()可以冻结我的程序,即使我在不同的线程中运行它。我

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

我的工作: 我将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);

提前谢谢

那很容易。永远不要在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的模式完成的。你真的应该使用数据绑定


数据绑定将处理所有
调度程序
调用。

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

有许多方法可以将耗时的操作委托给后台线程,并在UI线程上分派UI调用

SmsSender sms = new SmsSender();
DataView result = sms.GetAllInboxMessagesDataSet().Tables[0].DefaultView
Action action = () =>
{
    dgUser1.ItemsSource = result;
};
dgUser1.Dispatcher.BeginInvoke(action);
简单的例子是使用
BackgroundWorker
。将非UI内容放入
DoWork
事件处理程序中,并在
RunWorkerCompleted
处理程序上执行UI操作,该处理程序仅在UI线程上调用,因此需要向UI Dispatcher分派调用

小样本-

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

这是故意的
Dispatcher.BeginInvoke()
只能在与UI交互的工作中被调用。我如何重新设计我的项目?有什么想法吗?
Dispatcher.BeginInvoke
在创建
Dispatcher
的线程上执行委托。通常,您使用它可以从另一个线程更新UI线程上的某些内容。由于您在委托中包含了耗时的调用,这意味着一切都在UI线程上运行。谢谢Aron。但我的用户界面挂了。我是WPF的新手。你能告诉我如何使用数据绑定吗?超出了这里快速回答的范围。请用谷歌搜索WPF教程。任何人都会描述MVVM模式以及如何在WPF中实现它。谢谢。您应该在worker\u DoWork正文中使用Dispatcher+1对于您,只有当
SmsSender
是UI对象时,工作才需要Dispatcher。如果不是,则不需要使用dispatcher。