我有一个非常复杂的 UserControl 需要在运行时创建。此创建将 GUI 冻结大约 5 秒(这是不可接受的)。
我试图将此操作移至后台工作人员并最终出现此异常:
调用线程必须是 STA,因为许多 UI 组件都需要这个。
我知道我不能使用 MTA 线程来创建 UserControl / UI 元素。我尝试使用 BackgroundWorker 和 Dispatcher 的组合,但它不起作用。
第一次尝试
private void LetsGo()
{
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
DispatcherOperation dispatcherOperation = Dispatcher.CurrentDispatcher.BeginInvoke(new Action(this.GenerateControlAsync), DispatcherPriority.Background);
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
// Cancelled
}
else if (e.Error != null)
{
//Exception Thrown
}
else
{
//Completed
}
}
private void GenerateControlAsync () {
this.Control = new TimeConsumingUserControl();
}
上面的代码不起作用,this.GenerateControlAsync 方法没有执行。
第二次尝试
private async void GenerateControl()
{
this.Control = await Dispatcher.CurrentDispatcher.InvokeAsync<UserControl>(this.GenerateControlAsync);
}
private UserControl GenerateControlAsync()
{
return new TimeConsumingUserControl();
}
此示例正在运行,但它一直冻结 GUI 线程。
我正在使用 WPF 和 .net Framework 4.5。
请注意,GenerateControlAsync() 方法并不简单地创建 UserControl 的实例,还涉及更多逻辑。
回答@HighCore的问题:事实上,UserControl 的XAML 代码是通过XSLT 从xml 文件中转换出来的,而Codebehind 是使用CodeDOM 生成的。整个事情都需要编译并包装到一个程序集中。我使用 assembly.CreateInstance() 来获取 UserControl 的一个实例。此行引发引用的异常。在我的 GUI 中,我有一个 ContentControl,它绑定到我的 ViewModel 中的 UserControl。生成的数据(如需要转换的 xml 文件)是从 Web 服务中检索的。
这就是为什么执行此方法所需的时间比人们预期的要长的原因。