WPF:调用线程无法访问此对象,因为另一个线程拥有它 [英] WPF: The calling thread cannot access this object because a different thread owns it

查看:71
本文介绍了WPF:调用线程无法访问此对象,因为另一个线程拥有它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道还有类似的问题,例如在这里,我查看了所有内容,但它们似乎对我不起作用.

I know there are similar questions like Here And Here, I looked them all, but they seems not work for me.

我有一个线程:

private void Sample()
{
      Thread t = new Thread(new ThreadStart(Sample_Thread));
      t.SetApartmentState(ApartmentState.STA);
      t.Start();
}

在Sample_Thread中,我以前称为 MessageBox ,它工作正常.

In the Sample_Thread, I previously called MessageBox which works fine.

private void Sample_Thread()
{
     try{ ... }
     catch(Exception e)
     {
          MessageBox.Show("SampleText");
     }
}

现在,我尝试调用 ModernDialog 而不是 MessageBox ,它给我错误'调用线程无法访问该对象,因为另一个线程拥有该对象.所以我将代码更改为此:

Now I try to call ModernDialog instead of MessageBox, it gives me error 'The calling thread cannot access this object because a different thread owns it.' so I change my code to this:

private void Sample_Thread()
{
     try{ ... }
     catch(Exception e)
     {
            Dispatcher.CurrentDispatcher.Invoke(() =>
            {
                ModernDialog.ShowMessage("SampleText");
            });
     }
}

但是仍然出现相同的错误,我该如何解决?谢谢!

But this still got that same error, how should I fix this? Thanks!

推荐答案

有很多重复项,所有重复项都起作用,并且所有重复项都相同:您不能从另一个线程修改UI.显示消息框确实修改了UI.此限制适用于至少追溯到Windows 95 其他操作系统(例如Linux)的所有Windows版本.

There are a lot of duplicates, all of which work and all of which say the same thing: You can't modify the UI from another thread. Displaying a messagebox does modify the UI. This restriction applies to all versions of Windows going back at least to Windows 95 and other OSs like Linux.

您不需要 Invoke 来更新UI或原始线程即可在后台执行任何操作..NET允许您使用 Task.Run 在后台执行工作,等待其结果并处理任何异常.您唯一需要写的是:

You don't need Invoke to update the UI or raw threads to perform anything in the background either. .NET allows you to execute work in the background with Task.Run, await its result and handle any exceptions. The only thing you need to write is :

private void SomeMethod()
{
...
}

private async void myButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        await Task.Run(someMethod);
    }
    catch(Exception e)
    {
        ModernDialog.ShowMessage(e.ToString());
     }
}

如果要在后台处理时更新UI(例如,显示进度),则可以使用 IProgress<T> 作为

If you want to update the UI while processing in the background, eg to display progress, you can use the IProgress< T> as explained here, to report using any type as a message, eg int, string or a full class :

private void SomeMethod(IProgress<string> progress)
{
   foreach(...)
   {
       progress.Report("foo");
       ....
   }
}

private async void myButton_Click(object sender, RoutedEventArgs e)
{
    var progressIndicator = new Progress<string>(reportProgressMethod);
    try
    {
        await Task.Run(()=>someMethod(progressIndicator());
    }
    catch(Exception e)
    {
        ModernDialog.ShowMessage(e.ToString());
    }
}

async void 仅应用于事件处理程序.在所有其他情况下,不返回结果的异步方法的方法签名应为 async Task

async void should only be used for event handlers. In all other cases, the method signature of an asynchronous method that doesn't return a result should be async Task

这篇关于WPF:调用线程无法访问此对象,因为另一个线程拥有它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆