gpt4 book ai didi

wpf - async-await 似乎使用了 UI 线程

转载 作者:行者123 更新时间:2023-12-01 09:58:47 24 4
gpt4 key购买 nike

在 View 模型中,我使用工厂:

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 View 中,我想在构造函数中设置 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)太:由于嵌套等待,请参阅评论。

最佳答案

我发现将 ViewModel 视为具有 UI 线程关联性最有用。将其视为逻辑 UI,即使它不是实际的 UI。因此,ViewModel 类上的所有属性和可观察集合更新都应该在 UI 线程上完成。

在您的 async方法,如果不需要返回UI线程,那么可以使用ConfigureAwait(false)避免在 UI 线程上恢复。例如,如果您的各种初始化方法是独立的,您可以这样做:

private async Task<BaseData> InitializeAsync()
{
// Start all methods on the UI thread.
var instancesTask = InstancesAsync();
var projectsTask = ProjectsAsync();
var adminTask = AdminAsync();

// Await for them all to complete, and resume this method on a background thread.
await Task.WhenAll(instancesTask, projectsTask, adminTask).ConfigureAwait(false);

return this;
}

另外,只要您有 return await ,再看看能不能避免 async/ await完全:
public static Task<BaseData> CreateAsync()
{
var ret = new BaseData();
return ret.InitializeAsync();
}

最后,你应该强烈避免 Dispatcher .您的 Loaded事件可以简化为:
Loaded += async ()
{
DataContext = await BasisGegevens.CreateAsync();
};

关于wpf - async-await 似乎使用了 UI 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20052995/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com