这是我的第一篇文章,如果我犯错,请原谅我。
我有一个返回字符串的Task。在该任务中,我想打开一个用户输入代码的新窗口。输入代码并关闭窗口后,Task将返回代码。
我的代码如下:
public Task<string> GetLoginCode()
{
return Task.Run(() =>
{
CodeRequestView view = new CodeRequestView();
CodeRequestViewModel viewModel = new CodeRequestViewModel();
view.ShowDialog();
return viewModel.Code;
});
}
我遇到的问题是当我运行我的项目时我收到了一个&#34;调用线程必须是STA,因为许多UI组件都需要这个。&#34; CodeRequestView.xmal.cs文件的构造函数中的异常。
如何解决这个问题的一些帮助将不胜感激。 谢谢!
答案 0 :(得分:3)
当你从非UI线程调用UI
内容时,你可以使用像Dispatcher
这样的UI线程。
public Task<string> GetLoginCode()
{
return Task.Run(() =>
{
CodeRequestViewModel viewModel = new CodeRequestViewModel();
Application.Current.Dispatcher.Invoke(delegate
{
CodeRequestView view = new CodeRequestView();
view.ShowDialog();
});
return viewModel.Code;
});
}
答案 1 :(得分:1)
WPF窗口和控件需要在其apartment state的STA线程上运行。 Task.Run()
使用线程池,它被定义为MTA,并且不允许它们实例化必须在STA线程上的Window子类对象。
在使用它创建新的窗口对象之前,您需要手动创建一个新线程,并将其公寓状态设置为STA。由于您没有显示完整代码,因此我不知道为什么需要返回Task<string>
对象而不是string
对象。如果你想让它以异步方式运行(等待),你使用Task.Run()
的原始实现已经在另一个线程(来自线程池)上运行它,并立即返回给调用者。
无论如何,这是一个例子:
public string GetLoginCode()
{
string retVal;
Thread viewThread = new Thread(() =>
{
CodeRequestView view = new CodeRequestView();
CodeRequestViewModel viewModel = new CodeRequestViewModel();
view.ShowDialog();
retVal = viewModel.Code;
});
}
viewThread.SetApartmentState(ApartmentState.STA);
viewThread.Start();
return retVal;
}
我从来没有试过这个,所以我不确定返回值是否会导致同步问题。