【问题标题】:Is processes threads (or whole process) suspended进程线程(或整个进程)是否已挂起
【发布时间】:2013-08-16 07:40:25
【问题描述】:

我想检查进程的线程(整个进程)是否被挂起。 我通过这段代码获取每个进程线程:

var threads = Proc.Threads;
for (int x = 0; x < threads.Count; x++) {
var thread = threads[x];

但是System.Diagnostics.ThreadState 不包含Suspended,但System.Threading.ThreadState 包含。如何将System.Diagnostics.ThreadState 转换为System.Threading.ThreadState,或者是否有其他方法可以检查它?我不是想暂停/恢复它们,只是想知道 Process hacker/Process explorer 是如何做到的。

【问题讨论】:

  • System.Threading 的一个就足够了,确定吗?你想做什么?在 MSDN 的诊断中,它说“线程状态枚举仅对少数调试场景感兴趣。您的代码永远不应使用线程状态来同步线程的活动。”一般来说,诊断不是您应该用于实际处理线程的工具
  • 操作系统线程与 .Net 线程不同。 Process.Threads 返回操作系统线程,每个线程可能对应也可能不对应 .Net 线程。你可以看看ProcessThread.WaitReason,但它不对应.Net等待状态。
  • @Matthew Watson 如果你愿意写这个作为答案,我会批准的。

标签: c# multithreading process


【解决方案1】:

Microsoft 在 .NET 1.0 版中犯了一个大错误,他们添加了 Thread.Suspend() 和 Resume() 方法。这些方法被广泛滥用,程序员使用它们来实现线程同步。他们是完全不合适的。问题是它通常有效。但是在不走运的时候调用 Suspend(),当线程被隐藏在 Windows 调用中时,你会冻结一个线程,并持有一个全局锁。并导致整个程序死锁。

这不是他们犯的唯一设计错误,集合类上的 Synchronized 方法也是一场灾难。被广泛误解为“返回一个线程安全的集合”。

生活和学习,这一切都在 .NET 2.0 中得到了解决。一项重大改革是线程可能不再一定是操作系统线程,它从未真正实现过。但解释了为什么有 两个 ThreadState 枚举,一个用于 Thread(.NET 版本),另一个用于 ProcessThread(操作系统版本)。他们关闭了程序员滥用 Suspend/Resume 的漏洞,这些方法被宣布为过时。而且他们也关闭了后门,你从ProcessThread中查不到有线程被挂起。

功能,而不是错误。不要犯同样的错误,知道线程被挂起是无用的知识,它很可能在微秒后不再被挂起。

【讨论】:

  • +1 - 我很乐意听到关于 .NET 线程支持的问题 - 这让我自己的问题看起来不那么令人担忧了:)
【解决方案2】:

操作系统线程与 .Net 线程不同。 Process.Threads 返回操作系统线程,每个线程可能对应也可能不对应一个 .Net 线程。

你可以查看 ProcessThread.WaitReason,但它不对应 .Net 等待状态

【讨论】:

    【解决方案3】:

    这会对某人有所帮助。

            Process proc = Process.GetProcessById(31448);
            if(proc.Threads[0].WaitReason == ThreadWaitReason.Suspended)
            {
                //process is suspended
            }
    

    【讨论】:

    • 这正是我想要的,谢谢!
    【解决方案4】:

    你可以不恰当地使用SuspendThread或Wow64SuspendThread来判断它是否被挂起,然后使用ResumeThread来恢复情况。

    SuspendThread return: "如果函数成功,则返回值为线程之前的挂起计数;"

    声明:

        [Flags] public enum ThreadAccess : int {
            TERMINATE = (0x0001),
            SUSPEND_RESUME = (0x0002),
            GET_CONTEXT = (0x0008),
            SET_CONTEXT = (0x0010),
            SET_INFORMATION = (0x0020),
            QUERY_INFORMATION = (0x0040),
            SET_THREAD_TOKEN = (0x0080),
            IMPERSONATE = (0x0100),
            DIRECT_IMPERSONATION = (0x0200)}
    
        [DllImport("kernel32.dll")]
            static extern IntPtr OpenThread(
            ThreadAccess dwDesiredAccess,
            bool bInheritHandle,
            uint dwThreadId);
    
        [DllImport("kernel32.dll")]
            static extern uint SuspendThread(IntPtr hThread);
    
        [DllImport("kernel32.dll")]
            static extern int ResumeThread(IntPtr hThread);
    
        [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] 
            static extern bool CloseHandle(IntPtr handle);
    

    (Wow64SuspendThread 链接隐藏,因为我需要 10 个声誉才能放置 2 个链接 = ht.tps://msdn.microsoft.com/it-it/library/windows/desktop/ms687400(v=vs.85).aspx )

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-22
      • 2012-08-02
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多