Bar*_*Lib 0 c# wpf multithreading
我知道有类似的问题,比如Here And Here,我看了他们一切,但他们似乎不适合我.
我有一个帖子:
private void Sample()
{
Thread t = new Thread(new ThreadStart(Sample_Thread));
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
Run Code Online (Sandbox Code Playgroud)
在Sample_Thread中,我之前调用过MessageBox哪个工作正常.
private void Sample_Thread()
{
try{ ... }
catch(Exception e)
{
MessageBox.Show("SampleText");
}
}
Run Code Online (Sandbox Code Playgroud)
现在我尝试调用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");
});
}
}
Run Code Online (Sandbox Code Playgroud)
但是这仍然有同样的错误,我应该如何解决这个问题呢?谢谢!
有很多重复,所有这些都有效,所有这些都是相同的:你无法从另一个线程修改UI.显示消息框会修改UI.此限制适用于至少返回到Windows 95 和其他操作系统(如Linux)的所有Windows版本.
您无需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());
}
}
Run Code Online (Sandbox Code Playgroud)
如果您想更新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());
}
}
Run Code Online (Sandbox Code Playgroud)
async void应该只用于事件处理程序.在所有其他情况下,应该是不返回结果的异步方法的方法签名async Task