4

編集を開始

これを行う「正しい」方法(4.5より前)は、ここで概説されているように、SynchronizationContextを使用することです:http://msdn.microsoft.com/en-us/magazine/gg598924.aspx

4.5ではSynchronizationContextはasync/awaitキーワードで自動的に処理されると思いますが、確認するのに十分な作業を行っていません。

4.0では、「TaskScheduler.FromCurrentSynchronizationContext」を使用して、現在のスレッドのコンテキストをキャプチャすることができます(私の場合、これにはHttpContextが含まれますが、BCLのさまざまな部分で同様の構造が提供されます)。

編集終了

主な質問は次のとおりです。

次は、タスクと「コンテキスト」を共有するための「安全な」メカニズムですか?

あまり詳しく説明しないと、私のユースケースでは、コンテキストをアクションに直接プッシュすることはできません。

public static class ContextCaller{
    [ThreadStatic]
    public static object SharedState;

    public static Task InvokeWithContext(this Action theAction){
        //We're still running in the "outer" context, 
        //so we can collect a variable and store it in the thread-static
        //field by closing it into the task.
        var context = new object();

        var t = new Task(()=>{
            try{
                //close in the context
                SharedState = context;
                theAction();
            }
            finally{
                //teardown the shared state.
                SharedState = null;
            }
        });
        t.Start();
        return t;
    }
}

そして今、クライアントコード:

//client code:
Action doWork = ()=>{
    var state = ContextCaller.SharedState;
    //do work on state, potentially throwing an exception in the process.
};

//cause the task to be invoked with some data available only on this thread.
doWork.InvokeWithContext();

タスクとスレッドの関係についての私の理解に基づくと、上記は安全であるはずです。理由は次のとおりです。

  1. 1つのタスクは正確に1つのスレッドで実行されます(アクションが追加のタスク/スレッドを生成しないことを前提としています)。
  2. ThreadStaticフィールドは、「theAction()」の実行前に設定され、「finally」は、結果に関係なく、「theAction()」の呼び出し後にこのフィールドがリセットされることを保証します。

「theAction」へのパラメーターを明示的に閉じる以外に、タスクのコンテキストを定義するための他のより良いパターンはありますか?

4

1 に答える 1

1

コードが正常に機能しないという技術的な理由はわかりません。

しかし、これを行うのは悪い習慣だと思います。他に方法がない場合にのみ、このようなものを使用します。そして、私はあなたのメソッドの別のオーバーロードを追加することAction<object>(またはより良いことに、強く型付けされたパラメーターを使用すること)は重要な変更ではないはずだと思います。

于 2012-12-14T22:59:04.260 に答える