Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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
将在后台线程中创建的wpf按钮添加到主窗口_Wpf_Multithreading - Fatal编程技术网

将在后台线程中创建的wpf按钮添加到主窗口

将在后台线程中创建的wpf按钮添加到主窗口,wpf,multithreading,Wpf,Multithreading,下面是我的场景:我有一个带有按钮的简单wpf窗口。当用户单击按钮时,我想创建另一个窗口(我们称之为子窗口),然后在背景线程上创建一个wpf按钮,将其添加到子窗口并显示子窗口。以下是此操作的代码: Button backgroundButton = null; var manualResetEvents = new ManualResetEvent[1]; var childWindow = new ChildWindow(); ma

下面是我的场景:我有一个带有按钮的简单wpf窗口。当用户单击按钮时,我想创建另一个窗口(我们称之为子窗口),然后在背景线程上创建一个wpf按钮,将其添加到子窗口并显示子窗口。以下是此操作的代码:

        Button backgroundButton = null;
        var manualResetEvents = new ManualResetEvent[1];
        var childWindow = new ChildWindow();
        manualResetEvents[0] = new ManualResetEvent(false);
        var t = new Thread(x =>
        {
            backgroundButton = new Button { Content = "Child Button" };
            childWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(()                   => childWindow.MainPanel.Children.Add(backgroundButton)));
            manualResetEvents[0].Set();
        });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();

        WaitHandle.WaitAll(manualResetEvents);
        childWindow.ShowDialog();

调用ShowDialog()时,出现以下错误“调用线程无法访问此对象,因为它属于另一个线程。”。我知道这个错误是因为添加到子窗口的按钮是在后台线程上创建的,因此我们得到了这个错误。问题是:我如何克服这个错误,并且仍然在后台线程上创建我的按钮

当您想从另一个线程访问父窗口时,每次都必须使用
调度程序
。我看到在线程的操作中,您使用
backgroundButton
。因此,您必须对
dispatcher.BeginIvoke
语句中的按钮执行任何操作 [编辑] 将线程操作更改为此

var t = new Thread(x =>
    {
        backgroundButton.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(()                   => backgroundButton = new Button { Content = "Child Button" }));
        childWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(()                   => childWindow.MainPanel.Children.Add(backgroundButton)));
        manualResetEvents[0].Set();
    });

我是根据你的代码写的。我没有检查你的代码,但希望它是正确的

当您想从另一个线程访问父级窗口时,每次都必须使用
调度程序。我看到在线程的操作中,您使用
backgroundButton
。因此,您必须对
dispatcher.BeginIvoke
语句中的按钮执行任何操作 [编辑] 将线程操作更改为此

var t = new Thread(x =>
    {
        backgroundButton.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(()                   => backgroundButton = new Button { Content = "Child Button" }));
        childWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(()                   => childWindow.MainPanel.Children.Add(backgroundButton)));
        manualResetEvents[0].Set();
    });

我是根据你的代码写的。我没有检查你的代码,但希望它是正确的

我怀疑这会起作用。创建时,在任何DispatcherObject上设置当前Dispatcher(按钮为DO)。之后没有办法改变它(不使用一些奇特的反射材料)。抱歉,您不能将子级添加到具有不同调度程序线程的视觉效果中,因为在调用Measure或Arrange时,渲染会导致InvalidOperationException。我怀疑这是否会起作用。创建时,在任何DispatcherObject上设置当前Dispatcher(按钮为DO)。之后没有办法改变它(不使用一些奇特的反射材料)。抱歉,您不能将子级添加到具有不同调度程序线程的视觉效果中,因为在调用Measure或Arrange.Javidan时,渲染会导致无效操作异常。我不太明白您的意思。您能详细说明或发布代码吗。那太好了Javidan.我不太明白你说的话.你能详细解释一下或张贴代码吗。那太好了