识别线程在调试器中的行

时间:2017-07-24 17:59:33

标签: c# multithreading visual-studio visual-studio-2017

我正在尝试调试一个多线程应用程序,其中几个线程似乎停止,然后在几分钟后继续工作或从不再工作。

我确信他们之间存在争论的原因,但我不知道如何找到它。在Visual Studio中使用Parallel StacksThreads视图仅向我提供了线程从哪里开始的堆栈,而不是它们当前的位置。

我以:

开始我的任务
Task task = new Task((object state) => { DoWork(state).GetAwaiter().GetResult(); }, $"worker_task{i}", TaskCreationOptions.LongRunning);

然后,他们会执行从ConcurrentQueue中提取项目并处理它们的过程。我使用了GetAwaiter().GetResult();,否则他们调用的异步方法会立即返回,并且即使仍在完成工作,任务也会显示为完成。

Visual Studio调试窗口:

enter image description here

线程#38880实际上并没有做任何工作,我想找出它被卡住的地方,但它只显示我在哪里开始任务。

如何查看任务/线程当前在哪一行?我是否以这样的方式开始我的任务,以至于我看不到这个?如果是这样,我该怎么办?

上下文:我正在运行通过Httpclient调用API的任务。由于网络延迟,我并行运行多个任务,以便在等待时间内最大化我的CPU利用率。调用Httpclient是一个异步操作,我似乎无法await创建任务,所以我最终创建了一个匿名函数并在其中阻塞。

这可能是错误的方法,但我不知道怎么回事。

启动任务的方法:

    private static void InitWorkers()
    {
        for(int i = 0; i < max_workers; i++)
        {
            Task task = new Task((object state) => { DoWork(state).GetAwaiter().GetResult(); }, $"worker_task{i}", TaskCreationOptions.LongRunning);

            ProcessingTasks.TryAdd($"worker_task{i}", task);
            processedStats.TryAdd($"worker_task{i}", new Stat());

            task.Start();
        }
    }

1 个答案:

答案 0 :(得分:3)

您的问题是.GetAwaiter().GetResult(),它会在等待任务完成时阻止调用线程 不要那样做。

如果您的方法真的是异步,则根本不需要创建Task;你可以调用它,它将异步地完成它的工作。

如果它在其同步部分中执行阻塞或CPU绑定调用,则应使用Task.Run()在后​​台线程中运行该调用并等待生成的任务。