如何读取 C# 应用程序中的线程名称?

How can I read the name of a thread in a C# application?

提问人:Dominique 提问时间:7/12/2023 最后编辑:Dominique 更新时间:7/13/2023 访问量:106

问:

我正在开发一个用 C# 编写的多线程应用程序。 我想验证线程是否已经在运行。

你可能会想“这有多容易?”,但似乎有一个问题:

特此查看我的线程窗口的屏幕截图:

enter image description here

如您所见,有一个 ID 为 42940 的线程,其“Name”属性为“通知图标”。

现在,我正在调试以下源代码:

foreach (ProcessThread thread in currentThreads)
{
    log.Debug($"Info about thread:Name=[], ID=[{thread.Id}], IsAlive=[]");
}

使用断点,我到达了 ID 为 42940 的线程。当我在监视窗口中显示此线程时,我看到的是:

enter image description here

如您所见,“thread”对象(ProcessThread 类的)似乎没有“Name”属性,尽管这在“Threads”窗口中非常明显。

我想访问源代码中的“Name”属性。
我该怎么做?

编辑:
显然,九年前有人问过同样的问题。看到我的问题是多么基本,我无法想象在九年的时间里,没有任何东西可以解决这个问题。有人有这方面的信息吗?如果还没有解决,有什么计划可以解决这个问题吗?

编辑(似乎根本不起作用):

我现在在我的项目中有以下代码:

foreach (ProcessThread thread in currentThreads)
{
    var hThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, false, thread.Id);
    SetThreadDescription(hThread, "Naam van de thread");
    var testdesc = GetThreadDescription(hThread, out string desc);
    var testGetThreadId = GetThreadId(hThread);
    log.Debug($"Info about thread:Name=[{desc}], ID=[{thread.Id}], description=[{testdesc}], testGetThreadId=[{testGetThreadId}]");

然而,变量的值始终是空字符串。desc

C# 多线程 对象 属性

评论

2赞 PaulF 7/12/2023
这回答了你的问题吗?从 ProcessThreadCollection 按名称获取正在运行的线程
0赞 Dominique 7/12/2023
@PaulF:显然,九年前,根据它的名字,不可能找到一个线程。现在仍然如此还是发现了问题?如果没有,是否有任何计划解决这个问题?(在我看来,我无法想象为了解决这个问题而采取任何措施)
1赞 Selvin 7/12/2023
您可以创建快照并迭代堆对象,找到线程并读取“_name”字段Microsoft.Diagnostics.Runtime
0赞 Dominique 7/12/2023
@Selvin:恐怕我已经尝试过了,但有一个问题:该库意味着需要在客户的 PC 上安装一个额外的库(以及其他库)。最重要的是,该库(如果我没记错的话)被称为 ,说服客户在他的系统上添加一个具有这样名称的未知库并不容易:-)*unsafe*.dll
2赞 Selvin 7/12/2023
然后,您需要自己构建线程的名称......线程的迭代应该只对调试有用......取决于这似乎是一个糟糕的设计

答:

2赞 shingo 7/12/2023 #1

也许您必须使用 Windows API:OpenThread GetThreadDescription。我尝试在 dotnet 源代码中搜索这些 API,但仅使用。SetThreadDescription

const int THREAD_QUERY_LIMITED_INFORMATION = 0x0800;
[LibraryImport("kernel32.dll", SetLastError = true)]
private static partial IntPtr OpenThread(int dwDesiredAccess,
         [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwThreadId);
[LibraryImport("kernel32.dll", SetLastError = true)]
private static partial IntPtr GetThreadDescription(IntPtr hThread,
         [MarshalAs(UnmanagedType.LPWStr)] out string ppszThreadDescription);
foreach (ProcessThread thread in currentThreads)
{
    var hThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, false, thread.Id);
    GetThreadDescription(hThread, out string desc);
    log.Debug($"Info about thread:Name=[{desc}], ID=[{thread.Id}], IsAlive=[]");
}

Dominique编辑:由于前面的答案似乎不起作用,因此已添加以下源行并成功工作:

[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetThreadId(IntPtr hThread);
...
var testGetThreadId = GetThreadId(hThread);
log.Debug($"Info about thread:ID=[{thread.Id}], testGetThreadId=[{testGetThreadId}]");

=> 这证明使用 工作正常。现在我们需要确定为什么调用总是返回一个空字符串。DllImportGetThreadDescription()

编辑2:
在“kernel32.dll”文件的“导出”列表中有一件奇怪的事情:

C:\"Program Files"\"Microsoft Visual Studio"\2022\Enterprise\SDK\ScopeCppSDK\vc15\VC\bin\dumpbin.exe /EXPORTS C:\Windows\System32\kernel32.dll

...
769  300 000255C0 GetTempPathW
770  301 00020CF0 GetThreadContext
771  302          GetThreadDescription (forwarded to api-ms-win-core-processthreads-l1-1-3.GetThreadDescription)
772  303 0003BA40 GetThreadErrorMode
773  304 0003BA60 GetThreadGroupAffinity
...

也许这些东西导致该功能不起作用?forwarded

评论

0赞 Dominique 7/12/2023
不幸的是,我的电脑似乎不知道 ,但被识别出来。供您参考,我的应用程序的目标框架是 。我在 PC 上安装的最高框架是 版本 .LibraryImportSetLastErrorMarshalAsUnManagedType.NET Framework 4.6.14.8
0赞 Dominique 7/12/2023
我已经用这个替换了,但似乎找不到线程名:。LibraryImport[DllImport("kernel32.dll", SetLastError = true)]
0赞 Dominique 7/12/2023
我也尝试过,使用另一个“kernel32.dll”,但这里也没有成功:.[DllImport("C:\\Windows\\SysWOW64\\kernel32.dll", SetLastError = true)]
0赞 Dominique 7/12/2023
的结果等于 2^28,这是什么意思?var test = GetThreadDescription(...)
0赞 shingo 7/12/2023
我正在使用 .net 7,我可以获取一些名称,让我尝试一个 .net 框架应用程序。