如何在没有AppDomain.GetCurrentThreadId()的情况下获取当前线程ID,以便它实际工作?

时间:2014-08-26 08:59:31

标签: c# multithreading atomic appdomain

由于AppDomin.GetCurrentThreadId()已过时

  

" AppDomain.GetCurrentThreadId已被弃用,因为它没有   当托管线程在光纤上运行时,提供稳定的Id(也就是说   轻量级线程)。要获取托管线程的稳定标识符,   在Thread上使用ManagedThreadId属性。   http://go.microsoft.com/fwlink/?linkid=14202"

我尽量不使用它。但是,解释说“Thread.CurrentThread.ManagedThreadId'工作是没有价值的,因为它不提供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(&#34; Sequence包含多个元素&#34;)。显然,例如在使用多个桌面时(我认为这只能通过将执行循环的线程复制到另一个id)来实现。

问题:

  1. AppDomain.GetCurrentThreadId是否被错误地声明为过时了?
  2. 如何制作声明&#34; Process.GetCurrentProcess()。Threads.OfType()。SingleOrDefault(x =&gt; x.ThreadState == System.Diagnostics.ThreadState.Running).Id&#34;原子,还是甚至可能?

1 个答案:

答案 0 :(得分:10)

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

在20世纪90年代和21世纪初期,这通常是一个很受欢迎的事情,其名称包括&#34;轻量级线程&#34;,共同常规,纤维,&#34;绿色线程&#34;这个想法是为了避免操作系统进行线程上下文切换,而是用软件上下文切换CPU寄存器。 SQL Server是此功能的主要受益者,它内置支持&#34;光纤模式&#34;。

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

我不知道任何实际实现IClrTask的CLR主机,SQL Server团队的失败肯定是一个大红旗。但是,这并没有排除这种可能性,您可能想要担心的一种情况是在支持托管语言的脚本的大型非托管应用程序的上下文中运行代码。 CAD程序就是一个典型的例子。

你不会在非常的情况下死在水中,你的代码实际上会在这种情况下运行,所以将你的激光设置为眩晕并向前推进。除了不得不忍受过时警告之外,最苛刻的解决方法就是推翻GetCurrentThreadId()。它非常快。