C#挂起所有线程

C#挂起所有线程,c#,multithreading,thread-safety,remote-debugging,visual-studio-debugging,C#,Multithreading,Thread Safety,Remote Debugging,Visual Studio Debugging,我有一个可能相当独特的问题。我有一个应用程序,当我不在场的时候,它会在一个无头的盒子上运行很长时间,但并不重要。我希望能够使用Visual Studio远程调试此应用程序。为此,我有如下代码: // Suspend all other threads to prevent loss // of state while we investigate the issue. SuspendAllButCurrentThread(); var remoteDebuggerProcess = new Pr

我有一个可能相当独特的问题。我有一个应用程序,当我不在场的时候,它会在一个无头的盒子上运行很长时间,但并不重要。我希望能够使用Visual Studio远程调试此应用程序。为此,我有如下代码:

// Suspend all other threads to prevent loss
// of state while we investigate the issue.
SuspendAllButCurrentThread();
var remoteDebuggerProcess = new Process
    {
        StartInfo =
            {
                UseShellExecute = true,
                FileName = MsVsMonPath;
            }
    };
// Exception handling and early return removed here for brevity.
remoteDebuggerProcess.Start();

// Wait for a debugger attach.
while (!Debugger.IsAttached)
{
    Thread.Sleep(500);
}
Debugger.Break();

// Once we get here, we've hit continue in the debugger. Restore all of our threads,
// then get rid of the remote debugging tools.
ResumeAllButCurrentThread();

remoteDebuggerProcess.CloseMainWindow();
remoteDebuggerProcess.WaitForExit();
这样做的想法是,我在不在的时候遇到了一个错误,应用程序会自动暂停并等待远程调试器连接,在第一次继续后,由于
调试器.Break
调用,远程调试器会自动获得正确的上下文


问题是:实现
SuspendAllButCurrentThread
结果证明是不平凡的
Thread.Suspend
已被弃用,我无法P/Invoke到
SuspendThread
,因为托管线程和本机线程之间没有一对一的映射(因为我需要保持当前线程处于活动状态)。如果可以避免的话,我不想在有问题的机器上安装VisualStudio。如何使其工作?

Thread.Suspend的主要问题是它会使某些对象处于不可用状态

从:

不要使用Suspend和Resume方法来同步 线程的活动。您无法知道线程的代码是什么 挂起时正在执行。如果在线程运行时挂起线程 在安全权限评估期间持有锁,在 AppDomain可能已被阻止。如果在线程运行时挂起它 执行类构造函数时,AppDomain中的其他线程 阻止尝试使用该类。死锁可能发生得非常严重 很容易

因此,当您试图查看这样一个无法使用的对象的内容时,您可能也会被锁定。因此,无论您使用什么来挂起其他线程,最终都可能出现相同的情况。因此,唯一的可能性是修改其他线程的实现,以便能够要求它们挂起自己:

我不能p/Invoke到SuspendThread,因为托管线程和本机线程之间没有一对一的映射

您也不能枚举托管线程,只能枚举非托管线程。实际上,它们之间有一对一的映射关系,它们只是让我们很难找到它。最初的目的是允许创建一个自定义CLR主机,该主机不使用操作系统线程来实现线程,这是希望使用光纤的SQL Server组的请求。这一点从未奏效,他们无法获得足够可靠的结果。不存在不使用实际操作系统线程的实际CLR主机

因此,您可以实际使用Process.GetCurrentProcess()线程来枚举所有线程。并通过pinvoking GetCurrentThreadId(),将其与ProcessThread.Id进行比较,避免挂起自己的线程

这将有多可靠只是一个猜测,不要尝试做任何激烈的事情,比如发送警报提醒您是时候附加调试器了。您可能已经挂起了一个在Windows中执行代码的线程,并获得了一个全局锁。以及CLR工作线程,如终结器线程或后台GC线程


更好的方法是使用一个单独的保护进程来完成所有这一切,就像调试器一样。使用在guard程序中创建的命名EventWaitHandle和主程序中的OpenExisting()。guard程序需要对该等待句柄和进程执行WaitAny()。您的主程序现在只需调用Set()即可唤醒守护程序。现在它可以安全地挂起所有线程。

可能是个愚蠢的问题,但是VS不允许远程调试而不需要跳转这些环吗?我一直认为您可以在不更改代码的情况下进行远程调试,但我必须承认,我只在本地进行过调试,假设我确实使用全局锁挂起Windows中的某些东西-调试器如何避免遇到此问题?其次,在本例中,我也会P/调用
SuspendThread
,而不是使用不推荐使用的
线程。Suspend
,对吗?它不会避免它。这就是调试器必须始终是独立进程的原因。是的,pinvoke它。好吧,你是说进程特定的全局锁?除此之外,作为调试器,是否有方法注册另一个调试器试图附加的通知?锁始终特定于进程,包括Windows全局锁。如果不是那样的话,你就不能杀死一个进程。调试器无法交互。我又加了一段,另加了一段。