c# - 如何在没有 AppDomain.GetCurrentThreadId() 的情况下获取当前线程 ID,使其真正起作用?

标签 c# multithreading atomic appdomain

由于 AppDomin.GetCurrentThreadId() 已过时

"AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the ManagedThreadId property on Thread. http://go.microsoft.com/fwlink/?linkid=14202"

我试着不使用它。但是,“Thread.CurrentThread.ManagedThreadId”会起作用的解释毫无值(value),因为它没有提供 Win32 线程 ID,我需要它来进行 Win32 调用。所以我自己实现了如下。

public sealed class AppDomainExtender
{
    public static int GetCurrentThreadId_New()
    {
        return Process.GetCurrentProcess().Threads.OfType<ProcessThread>().SingleOrDefault(x => x.ThreadState == System.Diagnostics.ThreadState.Running).Id;
    }
}

现在有两个问题。

  • 如果可行,它的作用是否与 AppDomain.GetCurrentThreadId 完全相同?
  • 它不起作用的原因是运行的线程在循环 SingleOrDefault 循环时可能会发生变化。这种行为很奇怪,但它只是让我得到了一个 InvalidOperationException(“序列包含多个元素”)。显然,例如在使用多个桌面时会发生这种情况(我认为这只能通过将正在执行循环的线程复制到另一个 ID 来实现)。

问题:

  1. AppDomain.GetCurrentThreadId 是否被错误地声明为已过时?
  2. 如何使语句“Process.GetCurrentProcess().Threads.OfType().SingleOrDefault(x => x.ThreadState == System.Diagnostics.ThreadState.Running).Id”成为原子的,或者甚至可能?

最佳答案

AppDomain.GetCurrentThreadId() 的弃用是一个不便的事实,当然不是“虚假”声明。从 .NET 2.0 开始,.NET 线程和操作系统线程之间的关联被打破。自定义 CLR 主机可以通过实现 IClrTask interface 以其认为合适的方式自由实现线程。 .或者换句话说,您无法保证两个不同的 .NET 线程使用具有不同线程 ID 的不同操作系统线程。

在 1990 年代和 2000 年代初期,这通常是一种流行的做法,被称为“轻量级线程”、协同例程、纤程、“绿色线程”等。这个想法是为了避免线程上下文由操作系统切换,并改为在软件中切换 CPU 寄存器。 SQL Server 是此功能的主要受益者,它内置了对“纤程模式”的支持。

虽然 SQL Server 团队获得了该功能,但他们最终决定不发布它。当他们无法使其足够稳定时,他们放弃了该项目。一个可能激发灵感的问题 this article , 在他们的项目到期的同年出版。这没有再试过。至少不是因为该功能被多核革命淘汰了。现代内核中上下文切换的成本主要由 CPU 缓存的状态决定,不可能与每个拥有自己的 L1 和 L2 缓存的内核竞争。

我不知道有任何 CLR 主机实际实现了 IClrTask,SQL Server 团队的失败无疑是一个大危险信号。然而,这并不排除这种可能性,您可能想要担心的场景是在支持以托管语言编写脚本的大型非托管应用程序的上下文中运行您的代码。 CAD 程序就是一个典型的例子。

非常不太可能的情况下,您会死在水中,您的代码实际上会在这种情况下运行,因此请将您的激光设置为眩晕并继续前进。除了必须忍受过时警告之外,最明智的解决方法是调用 GetCurrentThreadId()。 .它非常快。

关于c# - 如何在没有 AppDomain.GetCurrentThreadId() 的情况下获取当前线程 ID,使其真正起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25501823/

相关文章:

c# - 在 Startup.cs 中使 ConfigureServices 方法异步

C# 数组索引越界错误

c# - 在 C# 上解析 Delphi 项目文件

android - android相机和线程安全问题

c# - 使用 Windows Phone 7 解析包含数组的 JSON 对象

python - 如何在 Python 中传递和运行回调方法

ios - 使用ARC,每个线程都没有自动释放池是致命的吗?

c - 有没有办法在 C 中使函数成为原子函数?

c++ - #pragma omp atomic 与 OMP_NUM_THREADS=1 的性能问题

multithreading - 在 Clojure 中删除原子列表中项目的最佳方法