首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TaskCompletionSource是否保证等待代码将在名为TCS.TrySetResult的线程上继续运行?

TaskCompletionSource是否保证等待代码将在名为TCS.TrySetResult的线程上继续运行?
EN

Stack Overflow用户
提问于 2016-06-08 06:54:48
回答 1查看 457关注 0票数 2

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

代码语言:javascript
复制
public Task<int> TestMethod(int argument)
{
    var tcs = new TaskCompletionSource<int>();
    var task = tcs.Task;

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

    return task;
}

然后我等待着这个方法:

代码语言:javascript
复制
async int CallingMethod()
{
    var returnValue = await TestMethod(5);
    Console.WriteLine(returnValue);
    return returnValue;
}

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

代码语言:javascript
复制
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 (但仍然有一些代码很难被检查),因此这种行为似乎是有内嵌保证的。我说的对吗?

EN

回答 1

Stack Overflow用户

发布于 2016-06-08 08:24:45

这种行为是否得到保证,或者是否存在调用SynchronizationContext (或任何其他线程)的情况?

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

有几个原因,您的连续性,不内联在同一线程。一个是是否使用TaskCreationOptions.RunContinuationsAsynchronously。其他如当前的SynchronizationContextTaskScheduler都在IsValidLocationForInlining中。

代码语言:javascript
复制
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;
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37695275

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档