gpt4 book ai didi

c# - TaskCompletionSource 是否保证等待代码将在调用 TCS.TrySetResult 的线程上恢复?

转载 作者:太空宇宙 更新时间:2023-11-03 12:44:48 28 4
gpt4 key购买 nike

我有一个使用 TaskCompletionSource 包装回调的方法,如下所示:

public Task<int> TestMethod(int argument)
{
var tcs = new TaskCompletionSource<int>();
var task = tcs.Task;

LegacyMethodWithCallback(argument, (returnValue) => tcs.TrySetResult(returnValue));

return task;
}

然后我等待那个方法:

async int CallingMethod()
{
var returnValue = await TestMethod(5);
Console.WriteLine(returnValue);
return returnValue;
}

编辑:LegacyMethodWithCallback 是一种使用网络与服务器通信的方法。回调在属于我们专有线程池的线程上运行(这是实现自定义 SynchronizationContext 的原因)。自定义 SynchronizationContext 基本上是空白的,除了它的 Post 方法将委托(delegate)排入线程池。以下是调用 Post 时应演示的 SC 实现:

internal class ServiceSynchronizationContext : SynchronizationContext
{
public override void Post(SendOrPostCallback d, object state)
{
Console.WriteLine("Post " + d + ": " + state + " for " + this.serviceLogic.ServiceLogicId);

// Enqueue the delegate into our thread pool
}
}

我已经实现了自己的同步上下文,但我惊讶地发现 CallingMethod 似乎在调用 TrySetResult 的同一个线程(因此调用回调的同一个线程)上立即恢复。我最初希望继续通过 SynchronizationContext 发布。

这种行为是否得到保证,或者是否存在调用 SynchronizationContext(或任何其他线程)的情况?如果此行为不是完全确定的,我能否以某种方式控制它?

我彻底检查了 CallingMethod 恢复时的调用堆栈,似乎甚至没有考虑 SynchronizationContext(但仍有一些代码无法轻易查看),因此看起来确实可以保证这种行为。我说得对吗?

最佳答案

Is this behavior guaranteed or are there any cases in which the SynchronizationContext (or any other thread) is invoked?

SynchronizationContext(如果存在)始终由等待代码使用(除非 ConfigureAwait(false) 另有指定)。这意味着如果您无法控制等待代码,则不能假定等待代码将在您的线程上运行。

有几个原因让你的延续不被内联到同一个线程上。一个是是否使用 TaskCreationOptions.RunContinuationsAsynchronously。其他像当前的 SynchronizationContextTaskScheduler 都在 IsValidLocationForInlining 中:

internal static bool IsValidLocationForInlining
{
get
{
// If there's a SynchronizationContext, we'll be conservative and say
// this is a bad location to inline.
var ctx = SynchronizationContext.CurrentNoFlow;
if (ctx != null && ctx.GetType() != typeof(SynchronizationContext)) return false;

// Similarly, if there's a non-default TaskScheduler, we'll be conservative
// and say this is a bad location to inline.
var sched = TaskScheduler.InternalCurrent;
return sched == null || sched == TaskScheduler.Default;
}
}

关于c# - TaskCompletionSource 是否保证等待代码将在调用 TCS.TrySetResult 的线程上恢复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37695275/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com