私は自分のアプリケーションに待ち受けを実装しようとしていますが、いくつかの問題に直面しています。
簡単そうに見えますが、それではうまくいきません。以下のコードは、LoadAsyncがWCFサービス呼び出しを実行してデータを返すのを待ってから、Tasksフォームを読み込むことができます。しかし、await callを使用すると、Tasksフォームのインスタンス化に関するクロスUIスレッド例外が発生します。私が待たなければそれはうまくいく。何がおかしいのですか?
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");
}
}