调用线程无法访问此对象,因为不同的线程拥有它。'线程中的错误wpf

时间:2018-05-15 11:18:03

标签: c# wpf multithreading

我有一个窗口1,其中点击按钮我在新线程中打开窗口2。 以下是我的代码

 private void Button_Click_2(object sender, RoutedEventArgs e)
    {
        Thread thread = new Thread(() =>
        {
            Scanner w = new Scanner();
            w.Show();

            w.Closed += (sender2, e2) =>
            w.Dispatcher.InvokeShutdown();

            System.Windows.Threading.Dispatcher.Run();
        });

        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
    }

窗口2有表格我在按钮上点击

获取表格值
 private void EnterProduct(object sender, RoutedEventArgs e)
    {
        var data = ProductDetailsData;
        LoadCurrentBetween objMain = new LoadCurrentBetween(); //new MainWindow();
        objMain.fillorderform(data);
    }

在按钮上单击窗口2我将表单的值传递给另一个视图

public void fillorderform(dynamic data)
    {
        this.Dispatcher.Invoke(() =>
        {
            LoadCurrentdetails.Part = data.Part;
            LoadCurrentBetween loadCurrentbtw = new LoadCurrentBetween();
            Switcher.Switch(loadCurrentbtw);
        });          
    }  public static class Switcher
{
    public static MainWindow pageSwitcher;

    public static void Switch(UserControl newPage)
    {
        pageSwitcher.Navigate(newPage);
    }
}

以下代码在" this.Content = nextPage;"

给出错误
  

调用线程无法访问此对象,因为另一个线程拥有它。

public void Navigate(UserControl nextPage)
    {
        this.Dispatcher.Invoke(() =>
        {
        var aa = nextPage.Dispatcher.CheckAccess();

        this.Content = nextPage;
            });
    }

我见过其他开发者提出的类似问题,但我没有得到如何修复。 请帮忙

1 个答案:

答案 0 :(得分:1)

WPF非常严格(与Windows窗体相比),要求更新UI元素的方法在主/ UI线程上完成。所以你肯定希望两个窗口都在主/ UI线程中。你看到的错误是如果你尝试从另一个线程在WPF中进行UI工作会发生什么,所以你绝对不得不停止这样做。可以在同一个UI线程上打开多个窗口。

如果你的某个窗口正在进行重量级处理以使UI锁定,那么最简单的事情可能是将async关键字添加到按钮单击事件中,并将正在执行的工作放在另一个具有异步的方法中关键词。然后,当您调用helper方法时,使用await关键字。

我同意其他人的看法,BackgroundWorker和Task是另外两种在后台线程中完成重量级处理的方法,同时还具有响应式UI。任务比BackgroundWorker更容易使用。

如果您使用的是BackgroundWorker,则使用RunWorkerCompleted事件可能已经足够了。如果是这样,请看这篇文章:How to use WPF Background Worker。如果您正在使用BackgroundWorker,并且需要从后台线程调用UI类中的自定义方法,则将窗口/对话框的Dispatcher对象传递给后台线程(或以其他方式访问它),以及何时它需要回调到UI,使用Invoke和Dispatcher对象。通过使用Invoke,您从后台线程调用的方法将在UI线程上执行。