Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF:在UI线程和后台线程之间传递对象_C#_Wpf_Multithreading_Dispatcher - Fatal编程技术网

C# WPF:在UI线程和后台线程之间传递对象

C# WPF:在UI线程和后台线程之间传递对象,c#,wpf,multithreading,dispatcher,C#,Wpf,Multithreading,Dispatcher,在初始化Components之后的窗口构造函数中,我需要创建一个对象并将其绑定到datagrid。由于创建对象花费的时间太长,窗口需要一段时间才能显示。因此,我决定将对象的创建移动到后台线程,并通过执行dispatcher.invoke执行绑定来“委托回”UI线程。但这失败了 奇怪的是,如果我试图设置Dispatcher.invoke中的矩形的可见性,它可以工作,但DataGrid.setbinding不能!有什么想法吗?我在后台工作程序和threadstart上也尝试过同样的方法,但我总是遇到

在初始化Components之后的窗口构造函数中,我需要创建一个对象并将其绑定到datagrid。由于创建对象花费的时间太长,窗口需要一段时间才能显示。因此,我决定将对象的创建移动到后台线程,并通过执行dispatcher.invoke执行绑定来“委托回”UI线程。但这失败了

奇怪的是,如果我试图设置Dispatcher.invoke中的矩形的可见性,它可以工作,但DataGrid.setbinding不能!有什么想法吗?我在后台工作程序和threadstart上也尝试过同样的方法,但我总是遇到同样的错误。我无法访问DataGrid对象,即使它发生在dispatcher invoke委托中。我确信我在理解这是如何工作的过程中遗漏了一些东西。如有任何建议,将不胜感激。谢谢

StartupDelegate s = new StartupDelegate(CreateModel);
s.BeginInvoke(delegate(IAsyncResult aysncResult) { s.EndInvoke(aysncResult); }, null);

internal CreateModel()
{
    Model d = new Model();
    Dispatcher.Invoke( DispatcherPriority.Normal, 
                       new Action<Model>(
                          delegate(Model d1)
                          {
                              mModel = d1;   // mModel is a property defined in Window
                              Binding b = new Binding();
                              b.Source = mModel; 
                              MainDataGrid.SetBinding(TreeView.ItemsSourceProperty, mainb); // << dies here with - The calling thread cannot access this object because a different thread owns it.
                          }            
}
StartupDelegate s=新的StartupDelegate(CreateModel);
s、 BeginInvoke(委托(IAsyncResult aysncResult){s.EndInvoke(aysncResult);},null);
内部CreateModel()
{
模型d=新模型();
Dispatcher.Invoke(DispatcherPriority.Normal,
新行动(
代表(d1型)
{
mModel=d1;//mModel是在窗口中定义的属性
绑定b=新绑定();
b、 Source=mModel;

SetBinding(TreeView.ItemsSourceProperty,mainb);//我建议另一种方法

绑定不应该从代码中调用,而应该在XAML中定义它

您可以在窗口上再添加一个Model类型的DependencyProperty,将其称为“CurrentModel”,并将其初始值设置为NULL。看起来您已经有一个名为mModel的属性,该DependencyProperty是吗

您可以在XAML中定义CurrentModel到DataGrid或whichver控件的绑定


在您的委托末尾,Dispatcher.Invoke应该只设置CurrentModel,绑定将自动完成。

我建议另一种方法

绑定不应该从代码中调用,而应该在XAML中定义它

您可以在窗口上再添加一个Model类型的DependencyProperty,将其称为“CurrentModel”,并将其初始值设置为NULL。看起来您已经有一个名为mModel的属性,该DependencyProperty是吗

您可以在XAML中定义CurrentModel到DataGrid或whichver控件的绑定


在您的委托末尾,Dispatcher.Invoke应该只设置CurrentModel,绑定将自动完成。

您在调用哪个Dispatcher实例
Invoke

我猜执行
CreateModel
的是后台线程中的调度程序,而不是UI线程中的调度程序

DataGrid是一个控件,因此派生自
DispatcherObject
。每个这样的对象都通过其
dispatcher
属性公开其所有者线程的dispatcher,您应该使用该属性调用控件上的方法

在呼叫中更改调度程序应能正常工作:

internal CreateModel()
{
    Model d = new Model();

    // Invoke the action on the dispatcher of the DataGrid
    MainDataGrid.Dispatcher.Invoke( DispatcherPriority.Normal, 
                       new Action<Model>(
                          delegate(Model d1)
                          {
                              mModel = d1;   // mModel is a property defined in Window
                              Binding b = new Binding();
                              b.Source = mModel; 
                              MainDataGrid.SetBinding(TreeView.ItemsSourceProperty, mainb);
                          }            
}
internalcreatemodel()
{
模型d=新模型();
//调用DataGrid的调度程序上的操作
MainDataGrid.Dispatcher.Invoke(DispatcherPriority.Normal,
新行动(
代表(d1型)
{
mModel=d1;//mModel是在窗口中定义的属性
绑定b=新绑定();
b、 Source=mModel;
MainDataGrid.SetBinding(TreeView.ItemsSourceProperty,mainb);
}            
}
您还可以在执行后台操作之前将UI线程的调度程序存储在一个字段中,但是使用控件的调度程序可以更好地显示代码的意图:“我想在这个控件所属的任何线程上调用它”


更新:我刚刚意识到这是您控件的一个实例方法,因此您使用的dispatcher实例是正确的。深夜回答就到此为止。另外,您的代码对我很有用,用IEnumerable替换了您的模型。您的模型中有什么特别的地方吗?

关于哪个dispatcher实例,您是c调用
调用

我猜执行
CreateModel
的是后台线程中的调度程序,而不是UI线程中的调度程序

DataGrid是一个控件,因此派生自
DispatcherObject
。每个这样的对象都通过其
dispatcher
属性公开其所有者线程的dispatcher,您应该使用该属性调用控件上的方法

在呼叫中更改调度程序应能正常工作:

internal CreateModel()
{
    Model d = new Model();

    // Invoke the action on the dispatcher of the DataGrid
    MainDataGrid.Dispatcher.Invoke( DispatcherPriority.Normal, 
                       new Action<Model>(
                          delegate(Model d1)
                          {
                              mModel = d1;   // mModel is a property defined in Window
                              Binding b = new Binding();
                              b.Source = mModel; 
                              MainDataGrid.SetBinding(TreeView.ItemsSourceProperty, mainb);
                          }            
}
internalcreatemodel()
{
模型d=新模型();
//调用DataGrid的调度程序上的操作
MainDataGrid.Dispatcher.Invoke(DispatcherPriority.Normal,
新行动(
代表(d1型)
{
mModel=d1;//mModel是在窗口中定义的属性
绑定b=新绑定();
b、 Source=mModel;
MainDataGrid.SetBinding(TreeView.ItemsSourceProperty,mainb);
}            
}
您还可以在执行后台操作之前将UI线程的调度程序存储在一个字段中,但是使用控件的调度程序可以更好地显示代码的意图:“我想在这个控件所属的任何线程上调用它”

更新:我刚刚意识到这是控件的一个实例方法,因此您使用的dispatcher实例是正确的。S