0

私は自分のアプリケーションに待ち受けを実装しようとしていますが、いくつかの問題に直面しています。

簡単そうに見えますが、それではうまくいきません。以下のコードは、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");
        }
    });
}

1 답변


2

バックグラウンドスレッドからUIオブジェクトにアクセスすることはできません。Task.Runバックグラウンドスレッドでそのデリゲートを実行します。Task.RunUIにアクセスするデリゲート(例: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");
    }
}


  • THX - 私はTask.Runを削除しようとしたが、それは違いはありませんでした。悲しいことに追跡するのが非常に難しいバグ。 - Neal
  • 例外のスタックトレースを見てください。それはあなたに良い出発点を与えるでしょう。 - Stephen Cleary

関連する質問

最近の質問