我有一个创建任务和后续任务的WebService的。
在第一个任务中,我们设置Thread.CurrentPrincipal中
因此,当ContinuationTask启动时,它不再具有Thread.CurrentPrincipal中。
我想在ContinuationTask指定它应该在同一个线程作为其先行运行 。
我在网上搜索,但我只发现线程在运行的SynchronizationContext的要求,因此,我开始觉得我缺少一些基本的规则,特别是对于Thread.Principal应该如何工作。
首先,不要使用TaskContinuationOptions.ExecuteSynchronously
为了这个目的! 你不能强迫在同一线程上的延续。 它仅适用于非常高的概率。 总有一些地方不工作的情况:太多的递归调用将导致TPL不同步执行。 自定义TaskScheduler
s的也没有义务来支持这一点。
这是一个普遍的误解,特别是因为它被错误地传播在网络上。 下面是有关该主题的一些阅读: http://blogs.msdn.com/b/pfxteam/archive/2012/02/07/10265067.aspx
如果你需要在同一线程上运行,这样做:
Task.Factory.StartNew(() => { First(); Second(); });
太简单。
让我说明为什么作品通过展示一种替代解决方案:
void MyCompositeTask()
{
var result = First();
Second(result);
}
Task.Factory.StartNew(() => MyCompositeTask());
这看起来更直观:我们通过MyCompositeTask
到TPL运行。 该TPL不关心我们在回调做。 我们可以做任何我们想做的,包括调用多种方法和传递的结果。
从我的C#教材(C#4.0中果壳):
你可以迫使他们[续任务]通过指定同一个线程[他们的前因]上执行TaskContinuationOptions.ExecuteSynchronously
调用时ContinueWith
:这可能与减轻间接非常细粒度的延续提高性能。
原则上我还没有试过,但它似乎是你在找什么,并可以与结合Thread.CurrentPrincipal中使用。
这里是一个链接MSDN文章有一些更具体的例子,以及
设置池线程的身份是不是一个好主意。 它关系到你这个特定的线程,并与风险例外的情况下,“泄露”的身份,如果你忘了清除异常处理程序的身份。 您可以使用“泄漏”的身份运行不相关的任务结束了。
尝试通过WindowsIdentity对象的任务和使用假冒WindowsIdentity.Impersonate 。 这将允许你使用任何可用的线索,并安全地清除,即使发生异常的身份。
你可以尝试这样的事情:
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
语句确保即使发生异常模拟的标识被清除。
调用与TaskScheduler.FromCurrentSynchronizationContext()的延续:
Task UITask= task.ContinueWith(() =>
{
this.TextBlock1.Text = "Complete";
}, TaskScheduler.FromCurrentSynchronizationContext());
从复制https://stackoverflow.com/a/4331287/503969