如何使用VS C#2015调试器检查线程是否返回到线程池?
在我的情况下,有什么问题是无法通过逐行调试来检测它。
async Task foo()
{
int y = 0;
await Task.Delay(5);
// (1) thread 2000 returns to thread pool here...
while (y<5) y++;
}
async Task testAsync()
{
Task task = foo();
// (2) ... and here thread 2000 is back from the thread pool, to run the code below. I want
// to confirm that it was in the thread pool in the meantime, using debugger.
int i = 0;
while (i < 100)
{
Console.WriteLine("Async 1 before: " + i++);
}
await task;
}
在线程2000上运行的testAsync
的第一行中,调用foo
。遇到await Task.Delay(5)
后,线程2000返回到线程池(据称,我试图确认这一点),该方法等待Task.Delay(5)
完成。在此期间,控件返回给调用者,并且testAsync
的第一个循环也在线程2000上执行。
因此,在两个连续的代码行之间,线程返回到线程池并从那里返回。如何使用调试器确认?可能使用Threads调试器窗口?
为了澄清我的问题:foo
正在线程2000上运行。有两种可能的情况:
当它命中await Task.Delay(5)
时,线程2000返回线程池很短的时间,控件返回到调用者,在第(2)行,它将在线程2000上执行线程池。如果这是真的,那么你就无法轻易检测到它,因为Thread 2000在两个连续代码行之间的时间位于线程池中。
当它命中await Task.Delay(5)
时,线程2000不会返回线程池,但会立即从第(2)行开始执行testAsync
中的代码
我想验证哪一个确实在发生。
答案 0 :(得分:3)
您可以将Thread.CurrentThread.ManagedThreadId
打印到控制台。请注意,线程池可以自由地重复使用相同的线程来运行continuation,因此不能保证它会有所不同:
void Main()
{
TestAsync().Wait();
}
public async Task FooAsync()
{
int y = 0;
await Task.Delay(5);
Console.WriteLine($"After awaiting in FooAsync:
{Thread.CurrentThread.ManagedThreadId }");
while (y < 5) y++;
}
public async Task TestAsync()
{
Console.WriteLine($"Before awaiting in TestAsync:
{Thread.CurrentThread.ManagedThreadId }");
Task task = foo();
int i = 0;
while (i < 100)
{
var x = i++;
}
await task;
Console.WriteLine($"After awaiting in TestAsync:
{Thread.CurrentThread.ManagedThreadId }");
}
您可以检查的另一件事是ThreadPool.GetAvailableThreads
,以确定是否有其他工人已被分发使用:
async Task FooAsync()
{
int y = 0;
await Task.Delay(5);
Console.WriteLine("Thread-Pool threads after first await:");
int avaliableWorkers;
int avaliableIo;
ThreadPool.GetAvailableThreads(out avaliableWorkers, out avaliableIo);
Console.WriteLine($"Available Workers: { avaliableWorkers},
Available IO: { avaliableIo }");
while (y < 1000000000) y++;
}
async Task TestAsync()
{
int avaliableWorkers;
int avaliableIo;
ThreadPool.GetAvailableThreads(out avaliableWorkers, out avaliableIo);
Console.WriteLine("Thread-Pool threads before first await:");
Console.WriteLine($"Available Workers: { avaliableWorkers},
Available IO: { avaliableIo }");
Console.WriteLine("-------------------------------------------------------------");
Task task = FooAsync();
int i = 0;
while (i < 100)
{
var x = i++;
}
await task;
}
在我的机器上,这会产生:
Thread-Pool threads before first await:
Available Workers: 1023, Available IO: 1000
----------------------------------------------
Thread-Pool threads after first await:
Available Workers: 1022, Available IO: 1000
答案 1 :(得分:1)
我想验证哪一个确实在发生。
没有办法&#34;验证&#34;使用调试器,因为调试器用于模拟逻辑(同步)流 - 请参阅Walkthrough: Using the Debugger with Async Methods。
为了理解正在发生的事情(仅供参考,你的情况(2)),你需要了解await
从Asynchronous Programming with Async and Await开始的工作方式 - 异步方法部分,Control Flow in Async Programs和许多其他来源。
请看这个片段:
static void Main(string[] args)
{
Task.Run(() =>
{
// Initial thread pool thread
var t = testAsync();
t.Wait();
});
Console.ReadLine();
}
如果我们将lambda设为async
并使用await t;
而不是t.Wait();
,那么这就是初始线程将返回到线程池的点。如上所述,您无法使用调试器验证。但是看看上面的代码并从逻辑上思考 - 我们阻止了初始线程,所以如果它&#39;没有免费,您的testAsync
和foo
方法将无法恢复。但他们确实可以通过在 await
行之后设置断点来轻松验证 。