C# 暂停所有线程

标签 c# multithreading thread-safety remote-debugging visual-studio-debugging

我有一个可能相当独特的问题。当我不在场时,我有一个应用程序可以在 headless 盒上运行很长时间,但并不重要。我希望能够使用 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();

想法是这样的,当我不在的时候遇到了一个错误,应用程序有效地暂停了自己并等待远程调试器附加,在第一次继续之后自动获得正确的上下文,这要归功于 Debugger .Break 调用。

这就是问题所在:实现 SuspendAllButCurrentThread 被证明是非常重要的。 Thread.Suspend 已弃用,我无法 P/Invoke 到 SuspendThread 因为托管线程和 native 线程之间没有一对一的映射(因为我需要使当前线程保持事件状态)。如果可以避免,我不想在有问题的机器上安装 Visual Studio。我怎样才能使它工作?

最佳答案

I can't P/Invoke down to SuspendThread because there's no one-to-one mapping between managed threads and native threads

您也不能枚举托管线程,只能枚举非托管线程。实际上它们之间的一对一映射,只是很难找到它。最初的目的是允许创建一个不使用操作系统线程来实现 Thread 的自定义 CLR 主机,这是 SQL Server 组的一个请求,希望使用纤程来代替。这从来没有成功过,他们无法让它足够可靠。不使用实际操作系统线程的实际 CLR 主机不存在。

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

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

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

关于C# 暂停所有线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18285909/

相关文章:

c# - 在列表列表中查找项目

c# - 自动将 F# 转换为 C#

c# - WPF/C# : Is it considered bad practice to put resources in Application and casting Application. 当前访问它们?

multithreading - InterlockedRead在哪里?

java - java中如何更新大对象而不阻塞其他读取线程

c# - MonoTouch - 异步 UISearchBar

c++ - boost::system::error_code::message() 使用 boost::asio 套接字抛出访问冲突异常

C++:如果发生段错误或类似的事情,有没有办法杀死单个线程但保持应用程序运行?

java - 为什么DCL使用 volatile ,而不使用final?我代码运行同样的效果

java - doFilter() 中 servletRequest.setAttribute 线程安全吗?