在视图模型中,我使用了一个工厂:
期待的方法非常直截了当,例如:
在WPF视图中,我希望在构造函数中设置DataContext:
尽管它能够工作,但我感到非常不舒服,因为UI线程被广泛使用,包括在回调完成后等待的情况。我错过了什么吗?
此外,我不明白如何使用工厂模式来创建DataContext,因为如果没有上面的Invoke,我会收到一个不同线程拥有该对象的错误。
编辑:使用Cleary先生的想法,我得到了:
private async Task<BaseData> InitializeAsync()
{
await InstancesAsync();
await ProjectsAsync();
await AdminAsync();
return this;
}
public static async Task<BaseData> CreateAsync()
{
var ret = new BaseData();
return await ret.InitializeAsync();
}
期待的方法非常直截了当,例如:
var instances = await TaskEx.Run(new Func<List<string>>(() => Agent.GetInstances()));
在WPF视图中,我希望在构造函数中设置DataContext:
Loaded += delegate
{
Dispatcher.Invoke(new Action(async () => { DataContext = await BasisGegevens.CreateAsync(); }));
};
尽管它能够工作,但我感到非常不舒服,因为UI线程被广泛使用,包括在回调完成后等待的情况。我错过了什么吗?
此外,我不明白如何使用工厂模式来创建DataContext,因为如果没有上面的Invoke,我会收到一个不同线程拥有该对象的错误。
编辑:使用Cleary先生的想法,我得到了:
Loaded += async (object sender, RoutedEventArgs e) =>
{ DataContext = await BaseData.CreateAsync(); };
public static Task<BaseData> CreateAsync()
{
var ret = new BaseData();
return ret.InitializeAsync();
}
private async Task<BaseData> InitializeAsync()
{
// UI thread here
await InstancesAsync().ConfigureAwait(false);
// thread 'a' here
await ProjectsAsync().ConfigureAwait(false);
// thread 'a' sometimes 'b' here
await AdminAsync().ConfigureAwait(false);
// thread 'a' or 'b' here
return this;
}
这段代码运行良好,但我无法理解 ConfigureAwait(false)
的工作原理。
在方法 InstancesAsync()
中,我有一个等待的任务:
var instances = await TaskEx.Run(new Func<List<string>>(() => Agent.GetInstances()));
在等待响应后,我返回到UI线程 - 我从未预料到会发生这种情况!
请注意,ProjectsAsync()
和 AdminAsync()
的行为相同,尽管它们在工作线程(或后台线程)上启动!
我以为 ConfigureAwait(true)
会在调用线程中返回(在我的情况下是UI线程)。我测试了一下,确实如此。
但是,由于嵌套的等待,请看注释,为什么我也会看到这个问题出现在 ConfigureAwait(false)
中。
FrameworkElement.Loaded
事件,它应该在UI线程上触发。你是否在单独的线程上创建视图?那可能是因为你在非UI池线程上调用了Agent.GetInstances()
吗? - noseratio - open to workTaskEx.Run
使用一个独立的线程池来运行你的Func
委托,这就是Agent.GetInstances()
被执行的地方。我建议你遵循 Stephen 的回答,并确保 WPF UI 元素和 ViewModel 对象都在同一个 - UI - 线程上创建。添加一些记录 (System.Threading.Thread.CurrentThread.ManagedThreadId
) 来查看你所在的线程和位置。 - noseratio - open to workConfigureAwait(false)
只影响特定的await
,对于“内部”的await
没有影响。 - svick