在一个有很多异步线程的进程中,我给每个线程都设置了一个特定的名字,并定期监控它以查看其状态。不过,有些线程似乎经常会丢失其名称值。我不知道为什么会这样。
public static void ChangeThreadName(this Thread current, string newName)
{
if (string.IsNullOrEmpty(current.Name))
{
try
{
current.Name = newName;
}
catch (InvalidOperationException ex)
{
Log.Error(ex, $"Error when trying to change Threadname from [{current.Name}] to [{newName}]");
}
}
else
{
Log.Warning($"Trying to change Threadname from [{current.Name}] to [{newName}]");
}
}
在异步任务的 while 循环中:
if (Thread.CurrentThread.ManagedThreadId != originalID)
{
Log.Verbose($"Thread change detected at ThreadHandler{QueueID}-{threadNumberString}, oldID = {originalID} - newID = {Thread.CurrentThread.ManagedThreadId}");
nr = await ThreadManager.ReRegisterProc(nr, threadName, false);
originalID = Thread.CurrentThread.ManagedThreadId;
}
if (Thread.CurrentThread.Name != threadName)
{
Log.Verbose("ThreadName changed to {status} -> reverting to {args}", Thread.CurrentThread.Name, threadName);
Thread.CurrentThread.ChangeThreadName(threadName);
}
重命名和重新注册任务有效,但我不希望它是必需的。
我尝试将线程添加到静态列表并循环查看它的状态,如上所示,如果不重新注册,这是行不通的。
在
async
工作中,线程是 none of your business。你不能也不应该做任何依赖于特定线程的事情,包括(但不限于):
Monitor
跨越 await
[ThreadStatic]
异步和线程是完全不同的概念。没有“异步线程”这样的东西。有一个异步执行可能会发现自己在不同点的任意数量的不同线程之一上(可能在任何
await
切换)
如果您真的需要一些环境状态,请考虑
AsyncLocal<T>
,但老实说;最好避免环境状态
没有线程失去其
Name
属性。在您看来,这似乎正在发生,但事实并非如此。
你认为的线程不是单个线程,它是各种不同的线程,它们一直在幕后创建和销毁。
那是因为
async
使用了 ThreadPool 中的线程。
这意味着如果在某个时刻你有许多并行运行的异步任务,将创建新线程,如果在某个时刻你碰巧没有那么多(如果有的话)并行运行的任务,则旧线程可能会被销毁,并且所有这完全是你无法控制的。 (这应该是有争议的。)因此,新创建的线程似乎没有名字,而死亡的线程将把它们的名字带入坟墓。
我建议您为任务分配名称,而不是线程。