Douglas Gaskell Douglas Gaskell - 3 years ago 109
C# Question

Identifying line where thread is in debugger

I am trying to debug a multithreaded application where several threads seem to stall, and then continue working minutes later or never again.

I'm sure there is a point of contention between them that is causing this, but I don't know how to find it. Using the

Parallel Stacks
view in Visual Studio only provides me with the stack from of where the threads were started, not where they currently are.

I start my tasks with:

Task task = new Task((object state) => { DoWork(state).GetAwaiter().GetResult(); }, $"worker_task{i}", TaskCreationOptions.LongRunning);

They then run through a process of pulling items from a
and processing them. I used the
else the async method they call immediately returns and the tasks show as complete even though there is still work being done.

Visual Studio Debug windows:

enter image description here

Thread #38880 is not actually doing any work, and I want to find out where it is getting stuck, but it only shows me where the task was started.

How can I see what line the task/thread is currently on? Am I starting my tasks in such a way that I cannot see this? If so, what should I be doing?

Context: I am running tasks that call API's via
. Because of the network latency I am running multiple tasks in parallel to maximize my cpu utilization during wait time. Calling Httpclient is an async operation, and I can't seem to
the creation of a task, so I ended up creating an anonymous function and blocking inside of that.

This is probably the wrong approach, but I don't know how else to go about it.

Method that starts the tasks:

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());


Answer Source

Your problem is .GetAwaiter().GetResult(), which blocks the calling thread while waiting for the task to finish.
Don't do that.

If your method is truly async, you don't need to create a Task at all; you can just call it, and it will do its work asynchronously.

If it performs blocking or CPU-bound calls in its synchronous portion, you should use Task.Run() to run that in a background thread and wait for the resulting task.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download