簡體   English   中英

Task.Yield()之后失去SynchronizationContext

[英]SynchronizationContext lost after Task.Yield()

我一直在線程之間傳遞文化問題。 我已經設法使用同步上下文使它有些工作,但是在我的代碼的一部分中,我使用了Task.Yield()。 在這段代碼之后,我的上下文丟失了,這意味着在此之后的所有后續等待/收益都不要使用我的自定義SynchronizationContext。

我將其簡化為一個非常簡單的測試,可以看到在Task.Yield之后,我們的SynchronizationContext丟失了。

同步上下文類:

public class TestSynchronizationContext : SynchronizationContext
{
}

單元測試 :

[Test]
public async Task TestHere()
{
    TestSynchronizationContext context = new TestSynchronizationContext();
    SynchronizationContext.SetSynchronizationContext(context);
    var something1 = SynchronizationContext.Current;
    await Task.Yield();
    var something = SynchronizationContext.Current;
}

編輯:如果我使用一個新的任務,如果可以傳遞正確的TaskScheduler(盡管...這是調度程序,而不是同步上下文),將保留上下文。 如以下內容:

[Test]
public async Task TestHere()
{
    TestSynchronizationContext context = new TestSynchronizationContext();
    SynchronizationContext.SetSynchronizationContext(context);
    CultureInfo taskCulture = null;
        Task.Factory.StartNew(
            () => { taskContext = SynchronizationContext.Current; },
            CancellationToken.None,
            TaskCreationOptions.None,
            TaskScheduler.FromCurrentSynchronizationContext()
            ).Wait();
    Assert.AreEqual(context.GetType(), taskContext.GetType());
}

您的SychronizationContext必須將自己設置為Current 如果您的SynchronizationContext用於專用線程,則只需在主循環中設置一次即可。 如果它使用線程池線程來執行(如示例代碼中所示),則應在借用其中一個線程時進行設置(當然,在將線程返回線程池之前將其清除)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM