使用异步等待的跨UI线程无效操作
本文关键字:UI 线程 无效 操作 异步 等待 | 更新日期: 2023-09-27 18:16:30
我正在尝试在我的应用程序中实现异步等待,我遇到了一些困难
看起来很简单,但实际上并不是这样。我有下面的代码,我将通过等待LoadAsync执行WCF服务调用并返回数据,然后我可以加载任务表单。然而,通过await调用,我在task表单的实例化上得到了一个跨ui线程异常。如果我移除await,它就能工作。我做错了什么?
if (!Core.Tasks.IsLoaded)
{
await Core.Tasks.LoadAsync();
}
Core.ShowWait("Opening Tasks");
TasksForm frm = new TasksForm() { MdiParent = Core.MainMDIWindow, CurrentViewName = Core.CurrentUser.UserProfile.TasksLastViewName }; // <-- error on this line
LoadAsync方法是:
public override Task LoadAsync(bool includeDeleted = false)
{
return Task.Run(async () =>
{
Core.Logger.EnterMethod("_TasksData.Load");
try
{
DataSet = Core.LogbookProData.Tasks.GetTasks(DataUserID, includeDeleted);
LoadCompleted();
dsTasks cacheData = await Cache.LoadAsync(ConvertTimeZone);
if (cacheData != null)
MergeDataSets(DataSet, cacheData);
InitializeLayouts();
}
catch (Exception ex)
{
Core.Logger.LogException("_TasksData.Load", ex);
}
finally
{
Core.Logger.LeaveMethod("_TasksData.Load");
}
});
}
你不能从后台线程访问任何UI对象。Task.Run
在后台线程上执行它的委托,所以如果Task.Run
委托中有任何东西访问UI(例如,InitializeLayouts
听起来很可疑),那么你会得到这样的异常。
Task.Run
应该只在你有一个cpu绑定的操作,或者如果你只有一个阻塞API 应该是异步调用时才使用。它不是通常用于实现async
方法。你可能会发现我的async
/await
介绍帖子很有帮助。
例如,如果GetTasks
和MergeDataSets
阻塞时间不长,可以这样实现LoadAsync
:
public override async Task LoadAsync(bool includeDeleted = false)
{
Core.Logger.EnterMethod("_TasksData.Load");
try
{
DataSet = Core.LogbookProData.Tasks.GetTasks(DataUserID, includeDeleted);
LoadCompleted();
dsTasks cacheData = await Cache.LoadAsync(ConvertTimeZone);
if (cacheData != null)
MergeDataSets(DataSet, cacheData);
InitializeLayouts();
}
catch (Exception ex)
{
Core.Logger.LogException("_TasksData.Load", ex);
}
finally
{
Core.Logger.LeaveMethod("_TasksData.Load");
}
}