与前一个线程中的延续任务
本文关键字:线程 延续 任务 一个 | 更新日期: 2023-09-27 17:49:55
我有一个WebService来创建一个任务和一个延续任务。
在第一个任务中,我们设置了Thread。CurrentPrincipal因此,当ContinuationTask启动时,它不再具有Thread.CurrentPrincipal.
我想在ContinuationTask中指定它应该与其前一个在同一线程中运行。
我已经搜索了网络,但我只发现线程在SynchronizationContext中运行的要求,因此我开始认为我错过了一些基本规则,特别是关于如何线程。校长应该工作
首先,不要将TaskContinuationOptions.ExecuteSynchronously
用于此目的!不能在同一线程上强制执行延续。它只有在非常高的概率下才有效。总会有这样的情况:太多的递归会导致TPL不能同步执行。自定义TaskScheduler
也没有义务支持这个。
这是一个常见的误解,特别是因为它在网络上被错误地传播。下面是一些关于这个话题的阅读: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 in a Nutshell):
你可以通过在调用
ContinueWith
时指定TaskContinuationOptions.ExecuteSynchronously
来强制它们[延续任务]在[作为它们的前一个]线程上执行:这可以通过减少间接来提高非常细粒度的延续的性能。
原则上我还没有尝试过,但它似乎是你正在寻找的,可以与Thread.CurrentPrincipal结合使用。
这里是一篇MSDN文章的链接,还有一些更具体的例子
调用TaskScheduler.FromCurrentSynchronizationContext():
Task UITask= task.ContinueWith(() =>
{
this.TextBlock1.Text = "Complete";
}, TaskScheduler.FromCurrentSynchronizationContext());
复制自https://stackoverflow.com/a/4331287/503969
设置池线程的标识不是一个好主意。它将您绑定到这个特定的线程,并且如果您忘记在异常处理程序中清除标识,则有可能在发生异常时"泄漏"标识。您可能会以使用"泄漏"身份运行不相关的任务而告终。
尝试将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
语句确保即使发生异常也清除模拟的标识。