0

従来の VB6 コードでは、システム タイマーを使用してコールバックを実行し、イベント ハンドラーをブロックすることなくステート マシンを実行できるようにしました。疑似コードの例

Sub Unhooked(State info)
    Select Case info
        Case 1
            NextState = somestate1
        Case 2
            NextState = somestate2
        Case 3
            NextState = somestate3
    End Select
    RunStateMachine
End Sub

Sub RunStateMachine()
    MyObject.GoDoSomethingAndCallMeBack
End Sub

Sub MyObject_EventCallback(State info)
    APITimer.SetUpCallBackTarget (Unhooked, info)
    APITimer.CallMeBackInASec
End Sub

ステート マシンで何らかの呼び出しが行われ、後でイベント ハンドラーが起動され、コールバックを実行するタイマーがセットアップされ、イベント ハンドラー コードが次のコードに進む前に完了できるようになることを理解していただければ幸いです。州。

私は C# で同様の傾向を続けていますが、言語がこれを行うためのよりかわいい方法を提供すると確信しているため、それは間違っていると感じています。私の C# ステート マシンはまだ UI スレッドでイベントを発生させる VB6 オブジェクトを呼び出しているため、イベント ハンドラーを「フック解除」して、ステート マシンが途中で続行する前にイベント ハンドラーを解放するより良い方法はありますか?

BeginInvoke を使用してポンプにメッセージを追加してステート マシンを実行できると考えましたが、スレッド プール スレッドではなく同じスレッドで実行できますが、私のクラスはフォームまたはコントロールではありません。タイマーを使用しないソリューションを思いつくことができると思いますが、タイマーは非常に簡単に使用できるので、どんなアイデアでも素晴らしいでしょう.

4

1 に答える 1

1

Task当面の問題を解決するには、次のように UI スレッド コンテキストのキューに入れることができます。

var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => Unhooked(info), CancellationToken.None,
    TaskCreationOptions.None, ui);

SynchronizationContextオブジェクトがフォームまたはコントロールでなくても、UIを検出できます。の詳細については、MSDN の記事SynchronizationContextを参照してください。

コードにこれがたくさんある場合は、ヘルパー メソッドにラップすることをお勧めします。

public void CallbackLater(Action action)
{
  Task.Factory.StartNew(action, CancellationToken.None,
    TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}

void MyObject_EventCallback(State info)
{
  CallbackLater(() => Unhooked(info));
}

より広いスキームでは、 Async CTPを真剣に検討し、UI スレッド (つまり、イベント ベースの非同期パターン) でイベントを発生させる代わりに、タスク ベースの非同期パターン API を設計します。

于 2011-07-20T14:34:59.617 に答える