WPF:调用线程无法访问此对象,因为其他线程拥有它
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45730765/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF: The calling thread cannot access this object because a different thread owns it
提问by BarryLib
I know there are similar questions like HereAnd Here, I looked them all, but they seems not work for me.
我知道有类似的问题,例如HereAnd Here,我都看了一遍,但它们似乎对我不起作用。
I have a thread:
我有一个线程:
private void Sample()
{
Thread t = new Thread(new ThreadStart(Sample_Thread));
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
In the Sample_Thread, I previously called MessageBoxwhich works fine.
在 Sample_Thread 中,我之前调用过MessageBox它工作正常。
private void Sample_Thread()
{
try{ ... }
catch(Exception e)
{
MessageBox.Show("SampleText");
}
}
Now I try to call ModernDialoginstead 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:
现在我尝试调用ModernDialog而不是调用MessageBox,它给了我错误,'The calling thread cannot access this object because a different thread owns it.'所以我将代码更改为:
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!
但这仍然有同样的错误,我应该如何解决这个问题?谢谢!
回答by Panagiotis Kanavos
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 doesmodify the UI. This restriction applies to all versions of Windows going back at least to Windows 95 andother OSs like Linux.
有很多重复项,所有这些都有效,并且都说同样的话:您不能从另一个线程修改 UI。显示消息框确实会修改 UI。此限制适用于至少可以追溯到 Windows 95和其他操作系统(如 Linux)的所有 Windows 版本。
You don't need Invoketo 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 :
您也不需要Invoke更新 UI 或原始线程来在后台执行任何操作。.NET 允许您在后台执行工作Task.Run,等待其结果并处理任何异常。你唯一需要写的是:
private void SomeMethod()
{
...
}
private async void myButton_Click(object sender, RoutedEventArgs e)
{
try
{
await Task.Run(someMethod);
}
catch(Exception e)
{
ModernDialog.ShowMessage(e.ToString());
}
}
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 :
如果您想更新UI,而在后台处理,如显示进度,可以使用IProgress< T>如这里解释的,使用任何类型的消息,如int,字符串或满级汇报:
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 voidshould 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
async void应该只用于事件处理程序。在所有其他情况下,不返回结果的异步方法的方法签名应该是async Task

