簡體   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