C# 等待任务永远不会完成,即使其状态转换为';RanToCompletion';

C# 等待任务永远不会完成,即使其状态转换为';RanToCompletion';,c#,async-await,taskcompletionsource,C#,Async Await,Taskcompletionsource,首先,抱歉——我无法在一个适当简单的示例应用程序中重现这种行为。这个功能在调用代码重构之前就已经运行了 我正在尝试使用TaskCompletionSource发出异步操作结束的信号(长时间运行的进程正在完成,或者超时可能会使用TrySetResult()发出完成的信号) 我的问题是,尽管我看到任务正在从“WaitingForActivation”过渡到“RanToCompletion”,但等待的调用从未完成 作为测试,我创建了一个任务延续,并调用了它,我添加了一个计时器来显示任务状态: asyn

首先,抱歉——我无法在一个适当简单的示例应用程序中重现这种行为。这个功能在调用代码重构之前就已经运行了

我正在尝试使用TaskCompletionSource发出异步操作结束的信号(长时间运行的进程正在完成,或者超时可能会使用TrySetResult()发出完成的信号)

我的问题是,尽管我看到任务正在从“WaitingForActivation”过渡到“RanToCompletion”,但等待的调用从未完成

作为测试,我创建了一个任务延续,并调用了它,我添加了一个计时器来显示任务状态:

async Task<Foo> WaitForResultOrTimeoutAsync()
{
        //... [Create 'pendingReq' with its TaskCompletion property]

        TaskCompletionSource<Foo> myCompletion = pendingReq.TaskCompletion;

        Task<Foo> theTask = myCompletion.Task;

        var taskContinuation = theTask.ContinueWith(resp =>
        {
            Console.WriteLine("The task completed");
            return resp.Result;
        });

        new Timer(state =>
        {
            Console.WriteLine("theTask TaskCompletion state is {0}", theTask.Status);
            Console.WriteLine("taskContinuation TaskCompletion state is {0}", taskContinuation.Status);
        }, null, 0, 1000);

        //var result = await theTask;
        var result = await taskContinuation;
        Console.WriteLine("We're FINISHED");    // NEVER GETS HERE
        return result;
}

当然,随着接续被击中,直接等待任务也应该完成,不是吗?这种行为可能有哪些外部(调用)因素?

我非常确定调用堆栈上某个位置的调用代码阻塞了任务,并且该代码在同步上下文中执行(即,在UI线程上或从ASP.NET请求)。这将是我在博客上完整解释的内容。最正确的解决方案是将阻塞(通常是
Wait
Result
调用)替换为
Wait


未阻止带的
ContinueWith
的原因是它使用当前的
TaskScheduler
而不是当前的
SynchronizationContext
,因此在这种情况下,它可能会在线程池上运行。如果我对调用代码阻塞的猜测是正确的,那么如果将任务调度器传递给
TaskScheduler,则
ContinueWith
也会死锁。FromCurrentSynchronizationContext()

检查
SynchronizationContext.Current!=null
你能编辑你的代码吗?这样我们就可以运行它来复制你的问题了?谢谢@i3arnon——这确实是null,这让我走上了正确的道路@我的意思是不为空,对吗?@i3arnon在等待任何操作之前,它被设置为WindowsFormsSynchronizationContext。我指的是在延续中,它是空的。我怀疑这是由于Stephen关于使用TaskScheduler继续的注释…但没有进一步调查。是的,你说得很对。在调用堆栈的后面,我正在处理从synchronous调用一些异步代码的问题,并引用了Task.Result来实现这一点(我知道——淘气)。这与使用WinForms应用程序的Page_Load事件来测试此组件相结合,导致了您博客中描述的死锁。我随后一直使用async返回到原始调用方,问题得到了解决。在死锁等待上设置ConfigureAwait(false)也起到了作用。
theTask TaskCompletion state is WaitingForActivation
taskContinuation TaskCompletion state is WaitingForActivation
theTask TaskCompletion state is WaitingForActivation
taskContinuation TaskCompletion state is WaitingForActivation
The task completed
theTask TaskCompletion state is RanToCompletion
taskContinuation TaskCompletion state is RanToCompletion
theTask TaskCompletion state is RanToCompletion
taskContinuation TaskCompletion state is RanToCompletion