18

タスクと継続タスクを作成する WebService があります。

最初のタスクでは、Thread.CurrentPrincipalを設定します

したがって、ContinuationTask が開始されると、Thread.CurrentPrincipal がなくなります。

ContinuationTask、前件と同じスレッドで実行するように指定したいと思います。

私はウェブを検索しましたが、スレッドが SynchronizationContext で実行されるための要件しか見つかりませんでした。そのため、特に Thread.Principal がどのように機能するかに関して、いくつかの基本的なルールが欠けていると思い始めています。

4

4 に答える 4

16

まず第一に、TaskContinuationOptions.ExecuteSynchronouslyこの目的で使用しないでください! 同じスレッドで継続を強制することはできません。非常に高い確率でのみ機能します。機能しない場合が常にあります。再帰が多すぎると、TPL が同期的に実行されなくなります。税関TaskSchedulerもこれをサポートする義務はありません。

これはよくある誤解です。特に、ウェブ上で誤って広められているためです。そのトピックに関する読み物は次のとおりです。

同じスレッドで実行する必要がある場合は、次のようにします。

Task.Factory.StartNew(() => { First(); Second(); });

とても簡単。

別の解決策を示すことで、それが機能する理由を説明しましょう。

void MyCompositeTask()
{
  var result = First();
  Second(result);
}
Task.Factory.StartNew(() => MyCompositeTask());

これはより直感的に見えます: MyCompositeTaskTPL に渡して実行します。TPL は、コールバックで何をするかは気にしません。複数のメソッドを呼び出して結果を渡すなど、やりたいことが何でもできます。

于 2012-12-27T16:47:39.757 に答える
5

私の C# の教科書 (一言で言えば C# 4.0) から:

TaskContinuationOptions.ExecuteSynchronouslywhen callingを指定することで、それらの [継続タスク] を [継続元と同じ] スレッドで強制的に実行することがContinueWithできます。

原則として、私はこれを試していませんが、あなたが探しているものと思われ、Thread.CurrentPrincipal と組み合わせて使用​​ できます。

これは、いくつかのより具体的な例を含むMSDN記事へのリンクです

于 2012-12-27T16:27:34.250 に答える
3

TaskScheduler.FromCurrentSynchronizationContext() で継続を呼び出します。

Task UITask= task.ContinueWith(() =>
{
 this.TextBlock1.Text = "Complete"; 
}, TaskScheduler.FromCurrentSynchronizationContext());

https://stackoverflow.com/a/4331287/503969からコピー

于 2013-07-24T04:41:53.750 に答える
3

プール スレッドの ID を設定することはお勧めできません。この特定のスレッドに結び付けられ、例外ハンドラーで ID をクリアするのを忘れると、例外が発生した場合に ID が「漏えい」する危険があります。「リークされた」ID を使用して無関係なタスクが実行される可能性があります。

WindowsIdentity オブジェクトをタスクに渡し、 WindowsIdentity.Impersonate を使用して偽装してみてください。これにより、利用可能な任意のスレッドを使用できるようになり、例外が発生した場合でも ID を安全にクリアできます。

次のようなことを試すことができます:

WindowsPrincipal myPrincipal=...;
...
var identity=(WindowsIdentity)myPrincipal.Identity;
var task=Task.Factory.StartNew(ident=>{
        var id=(WindowsIdentity)ident;
        using(var context=id.Impersonate())
        {
            //Work using the impersonated identity here
        }
        return id;
    },identity).
.ContinueWith(r=>{
        var id = r.Result;
        using(var context=id.Impersonate())
        {
            //Work using the impersonated identity here
        }
});

このusingステートメントは、例外が発生した場合でも、偽装された ID が確実にクリアされるようにします。

于 2012-12-28T08:24:05.327 に答える