【问题标题】:Replacing AppDomain.GetCurrentThreadId(); with ManagedThreadId替换 AppDomain.GetCurrentThreadId();带有 ManagedThreadId
【发布时间】:2012-10-27 13:30:43
【问题描述】:

GetCurrentThreadId() 已被弃用,MSDN 声明 ManagedThreadId 取代了它。

但是,我得到了不同的结果,后者导致我的代码出现异常。我的代码改编自this post

        public static void SetThreadProcessorAffinity(params byte[] cpus)
        {
            if (cpus == null)
            {
                throw new ArgumentNullException("cpus");
            }

            if (cpus.Length == 0)
            {
                throw new ArgumentException(@"You must specify at least one CPU.", "cpus");
            }

            // Supports up to 64 processors
            long cpuMask = 0;
            byte max = (byte)Math.Min(Environment.ProcessorCount, 64);

            foreach (byte cpu in cpus)
            {
                if (cpu >= max)
                {
                    throw new ArgumentException(@"Invalid CPU number.");
                }

                cpuMask |= 1L << cpu;
            }

            // Ensure managed thread is linked to OS thread; does nothing on default host in current .NET versions
            Thread.BeginThreadAffinity();

#pragma warning disable 618
            // The call to BeginThreadAffinity guarantees stable results for GetCurrentThreadId,
            // so we ignore the obsolete warning.
            int osThreadId = AppDomain.GetCurrentThreadId();
            osThreadId = Thread.CurrentThread.ManagedThreadId;// NOT THE SAME VALUE
#pragma warning restore 618

            // Find the ProcessThread for this thread
            ProcessThread thread = Process.GetCurrentProcess().Threads.Cast<ProcessThread>()
                .Where(t => t.Id == osThreadId).Single();

            // Set the thread's processor affinity
            thread.ProcessorAffinity = new IntPtr(cpuMask);
        }

我可以看到问题是一个获取线程的进程 ID,而另一个获取应用的进程 ID。

如何在不使用已弃用方法的情况下使其工作?最初的 Stack Overflow 文章声明使用 P/Invoke,但我不知道如何使用,这不是 MSDN 声明的内容。

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    不,ManagedThreadId 与操作系统的线程 ID 完全没有关系。 CLR 只是简单地对线程进行编号,从 1 开始。这是 SQL Server 组中试图用纤程模拟 .NET 线程的项目的一个相当可悲的副作用。该项目被放弃了,他们无法使其足够稳定。遗憾的是,线程 ID 映射保留了 .NET 2.0 发布时的样子。从技术上讲,自定义 CLR 主机仍然可以使用该功能以他们想要的方式实现线程,我不知道有任何主流实现实际上这样做。 SQL Server 组故障是一个巨大的危险信号。

    绕过过时警告的唯一方法是 pinvoke GetCurrentThreadId()。该链接将带您进行正确的 pinvoke 声明。

    【讨论】:

    • 出于好奇,我假设 kernell32.dll 调用在 Mono 下不起作用?
    • "#pragma warning disable 0618" 在您使用 GetCurrentThreadId 的源文件中将抑制警告。
    • 关于 Neutrino 的评论,禁用 warning CS0618 将禁用该文件中的所有过时警告。这可以通过将目标代码包装在#pragma warning disable 0618 ...您的代码在这里...#pragma warning restore 0618 来本地化。 #pragma warning reference here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2019-08-07
    • 1970-01-01
    相关资源
    最近更新 更多