3

Trace.CorrelationManager.ActivityIdを使用してログエントリを相互に関連付けようとしています。しかし、私はこのコードがいつ終了するかを見つけています:

var result = await Task.Run(() => LongRunningMethod());

ActivityIdは、入力されたときの状態から変更されました。LongRunningMethod()では正しいですが(メソッドにはさまざまなトレースイベントがあります)、awaitが完了したときにのみ変更されるようです。

私の質問は、なぜActivityIdが変更されたのですか?

このコード行は、非同期で宣言された関数内にあり、MVCプロジェクトの非同期コントローラーアクションによって呼び出されます。

async public Task<ActionResult> Index()
{
...
var tasks = {list of Download<T> delegates}

var result = await Task.WhenAll(tasks)
}


async public Task<OperationResult> Download<T>(IEnumerable<T> data, Device device)
{
...
var result = await Task.Run(() => LongRunningMethod());

return result
}

おそらく私はasync/awaitまたはTaskメソッドを間違って使用していますか?基本的に、すべての「LongRunningMethod」を非同期で同時に開始し、すべてが終了するまで待機する必要があります。

4

2 に答える 2

10

あなたはそれを間違ってやっていないが、それはうまくいかないだろう。

WCFおよびASP.NET(MVCを含む)では、フレームワークが要求を実行する前に、現在のコンテキストをキャプチャするため、フレームワークを復元して、完了が元のスレッドで実行されるようにすることができます。

残念ながら、これはコントローラーが呼び出される前に発生します。システムのスナップショットは、ActivityIDを更新する前に発生します。続けて、コンテキストは設定する前の値にリセットされます。

タスクに.ConfigureAwait(false)を追加すると、継続を元のコンテキストで実行する必要がないため、アクティビティIDが復元されることがわかりました。

現時点では、CallContext.LogicalGetData /LogicalSetDataを使用して独自のActivityIDを管理する以外に、これに対するより良い解決策はありません。EventSourceProxyでの処理方法については、https://github.com/jonwagner/EventSourceProxy/commit/fa43c6acd07690dcd276346e3fcf25028f796b8cを参照してください。

これは、より深い説明の素晴らしい記事です。

http://sticklebackplastic.com/post/2007/08/14/One-mighty-gotcha-for-SystemDiagnostic-activity-Ids.aspx

于 2013-12-31T16:30:33.237 に答える
2

awaitキーワードを使用している理由は明確ではありません。必要なタスクの「継続」が必要ない場合は、を使用して開始します

var result = Task.Factory.StartNew(() => LongRunningMethod());

を呼び出した後にコードがある可能性があります(ただし、指定したコードの量が少ないため、保証されていません)await。バックグラウンドスレッドプールスレッドで実行awaitされるを実行するために使用されたものとは異なる同期コンテキストを使用して実行される継続がセットアップされます。LongRunningMethod()

これがお役に立てば幸いです。

于 2013-02-05T13:58:01.153 に答える