我正在尝试调试一个多线程应用程序,其中几个线程似乎停止,然后在几分钟后继续工作或从不再工作。
我确信他们之间存在争论的原因,但我不知道如何找到它。在Visual Studio中使用Parallel Stacks
和Threads
视图仅向我提供了线程从哪里开始的堆栈,而不是它们当前的位置。
我以:
开始我的任务Task task = new Task((object state) => { DoWork(state).GetAwaiter().GetResult(); }, $"worker_task{i}", TaskCreationOptions.LongRunning);
然后,他们会执行从ConcurrentQueue
中提取项目并处理它们的过程。我使用了GetAwaiter().GetResult();
,否则他们调用的异步方法会立即返回,并且即使仍在完成工作,任务也会显示为完成。
Visual Studio调试窗口:
线程#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();
}
}
答案 0 :(得分:3)
您的问题是.GetAwaiter().GetResult()
,它会在等待任务完成时阻止调用线程
不要那样做。
如果您的方法真的是异步,则根本不需要创建Task
;你可以调用它,它将异步地完成它的工作。
如果它在其同步部分中执行阻塞或CPU绑定调用,则应使用Task.Run()
在后台线程中运行该调用并等待生成的任务。