WPF:调用线程无法访问此对象,因为另一个线程拥有它 [英] WPF: The calling thread cannot access this object because a different thread owns it
问题描述
我知道还有类似的问题,例如在这里,我查看了所有内容,但它们似乎对我不起作用.
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屋!