繁体   English   中英

在与前一个相同的线程中继续执行任务

[英]Continuation Task in the same thread as previous

我有一个WebService,它创建一个任务和一个延续任务。

在第一个任务中我们设置Thread.CurrentPrincipal

因此,当ContinuationTask启动时,它不再具有Thread.CurrentPrincipal。

我想在ContinuationTask中指定它应该在与其前提相同的线程中运行

我搜索过网络,但我只发现线程要在SynchronizationContext中运行,因此我开始认为我缺少一些基本规则,特别是关于Thread.Principal应该如何工作。

首先,不要为此目的使用TaskContinuationOptions.ExecuteSynchronously 您不能强制在同一个线程上继续。 它只能以非常高的概率运行。 总有一些情况它不起作用:太多的递归会导致TPL不能同步执行。 Custom 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):

通过在调用ContinueWith时指定TaskContinuationOptions.ExecuteSynchronously ,可以强制它们[继续任务]在相同的线程[作为它们的前提]上执行:这可以通过减少间接来提高细粒度延续中的性能。

原则上我没有试过这个,但它似乎是你正在寻找的东西,可以与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()调用continuation:

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

复制自https://stackoverflow.com/a/4331287/503969

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM