c# - TaskFactory 内部任务永远不会被执行并且始终处于 WaitingForActivation 状态

标签 c# .net task-parallel-library task taskfactory

我正在使用 TaskFactory 使用以下代码启动新任务。

var task = Task.Factory.StartNew(async () =>
{
    await Task.Run(() =>
    {
        // Do API Call
        var saveResponse = doAPICall();
    }).ConfigureAwait(false);
}).Unwrap();

task.Wait();

doAPICall() 的代码如下所示,它调用返回任务的外部 API。

private string doAPICall()
{
    Task<string> response = client.FindBags(request);
    response.Wait(60000);

    if (response.Status == TaskStatus.RanToCompletion)
    {
        return response.Result;
    }
}

问题发生在 doAPICall() 函数中,任务“响应”状态永远不会更改为 RanToCompletion,并且始终处于 WaitingForActivation 状态。我已经尝试增加等待超时但仍然没有成功。我使用 TaskFactory 而不是 Task,因为将来我想创建自定义 TaskFactory 以更好地控制调度程序和并发性。

我的代码中是否缺少某些内部任务永远不会执行的东西?

编辑 我根据删除不必要的线程的注释修改了调用 doAPICall() 的代码,但仍然没有成功。 :-(

var task = Task.Factory.StartNew(() =>
{
    // Do API Call
        var saveResponse = doAPICall();
});

task.Wait();

最佳答案

您当前正在使用sync-over-fake-async-over-fake-async-over-sync-over-async。这真是一团糟。

请遵循以下准则:

  1. 不要使用Task.Factory.StartNew。曾经。 我使用 TaskFactory 而不是 Task,因为将来我想创建自定义 TaskFactory 以更好地控制调度程序和并发性。自定义任务调度程序不能很好地与异步代码配合使用。您可能必须采用更异步友好的解决方案来进行调度/并发。更多信息on my blog .
  2. 不要阻塞异步代码。我看到两个 Wait 调用和一个 Result,这两个调用都是严重的危险信号。更多信息on my blog .
  3. 不要在生产代码中使用Task.Status。它可以用于调试,但您不必将它用于实际逻辑。总有更好的解决方案。更多信息on my blog .
  4. 仅在 UI 层使用 Task.Run,而不是嵌套在帮助程序/库代码中。换句话说,用它来调用方法,而不是实现方法。更多信息on my blog .

从最里面的方法开始工作:

private async Task<string> doAPICallAsync()
{
  Task<string> responseTask = client.FindBags(request);
  // Note: it would be far better to use a cancellation token here instead of a "timed wait".
  Task timeoutTask = Task.Delay(60000);
  Task completedTask = await Task.WhenAny(responseTask, timeoutTask);
  if (completedTask == responseTask)
    return await completedTask;
}

您的调用代码将变为:

var saveResponse = await doAPICallAsync();

关于c# - TaskFactory 内部任务永远不会被执行并且始终处于 WaitingForActivation 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35884375/

相关文章:

.NET WinForms 自定义控件 : how to get a reference to the containing form

c# - 如何配置T4模板在不同项目中生成类

c# - System.Threading.ThreadAbortException 在新线程中引发

c# - 如何防止创建的线程多于可用的硬件线程数?

c# - 配置 Enterprise Library 5.0 数据访问应用程序 block

c# - 我应该将图像存储在数据库还是文件夹中?

.net - 针对.Net中的架构验证JSON

c# - 如何在 Powershell 中为实现 IDictionary 和 ICollection 的类的实例设置属性

c# - 如何在 Windows 中使用 UniDrv 或 XPS 驱动程序 v3 设置虚拟打印机和显示器

c# - MaxDegreeOfParallelism = Environment.ProcessorCount 减慢了我 CPU 的执行时间