2010-11-10 141 views
7

我的应用程序中有一个错误,只有当我在调试器中暂停应用程序几分钟时才会显示它的面部。我怀疑这是由于我使用的第三方网络库有一个心跳线程,当它在心跳线程暂停时无法ping服务器时,它会断开连接。在运行时暂停当前进程中的所有线程

我想写一个测试用例应用程序来验证这是错误的原因。为此,我需要一种方法来暂停应用程序中的所有线程(我将稍后缩小为仅暂停我怀疑可能是心跳线程的线程)以模拟暂停调试器中的应用程序。

有谁知道如何做到这一点?一个线程甚至有可能导致另一个线程进入睡眠状态?

谢谢, 亚历克斯

UPDATE:

我最终决定,我并不真的需要一个应用程序为我做到这一点,看到的一点是,只是为了验证,暂停在调试器正在导致断开连接。所以,在这里就是我所做的。(最简单的方法往往是最好的......或者至少是最简单的...)

private static void Main(string[] args) 
    { 
     IPubSubAdapter adapter = BuildAdapter(); 
     bool waitingForMessage; 
     adapter.Subscribe(_topic, message => waitingForMessage = false, DestinationType.Topic); 
     Stopwatch timePaused = new Stopwatch(); 
     while (adapter.IsConnected) 
     { 
      Console.WriteLine("Adapter is still connected"); 
      waitingForMessage = true; 
      adapter.Publish(_topic, "testmessage", DestinationType.Topic); 
      while (waitingForMessage) 
      { 
       Thread.Sleep(100); 
      } 
      timePaused.Reset(); 
      timePaused.Start(); 
      Debugger.Break(); 
      timePaused.Stop(); 
      Console.WriteLine("Paused for " + timePaused.ElapsedMilliseconds + "ms."); 
      Thread.Sleep(5000); // Give it a chance to realise it's disconnected. 
     } 
     Console.WriteLine("Adapter is disconnected!"); 
     Console.ReadLine(); 
    } 

和输出:

Adapter is still connected 
Paused for 10725ms. 
Adapter is still connected 
Paused for 13298ms. 
Adapter is still connected 
Paused for 32005ms. 
Adapter is still connected 
Paused for 59268ms. 
Adapter is disconnected! 

回答

4

您可以使用这种快速indentify你的进程的线程:

using System.Diagnostics; 

ProcessThreadCollection threads = Process.GetCurrentProcess().Threads; 

然后,你可以use kernel32.dll with P/Invoke做任何你需要这些线程。使用OpenThread获取所需线程的句柄,然后使用该句柄将其挂起并使用SuspendThread

这里有两种方法的的P/Invoke声明:

[DllImport("kernel32.dll")] 
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId); 

[DllImport("kernel32.dll")] 
static extern uint SuspendThread(IntPtr hThread); 
+0

看起来很有希望,由于引发异常,我给它一个去 – AlexC 2010-11-10 12:58:05

+0

随时回到这里,并告诉我们,如果它的工作。 :) – bitbonk 2010-11-10 13:04:12

+2

您还需要GetCurrentThreadId(),这样您才不会暂停自己。随机死锁很可能,不要分配任何东西。 – 2010-11-10 13:19:25

0

你可以把Thread.Suspend然后Thread.Resume方法,但这些已被取消,不recommneded使用它们。

但是,您可以执行以下操作: 有一个布尔标志,当设置您将线程置于一个大睡眠状态时。 或 更好使用ManualResetEvent

+0

谢谢,尽管如此,我需要获取所有线程对象的位置来完成此操作,而我无法找到它的枚举器。 (Process.Threads返回一个ProcessThreads集合,而不是线程) – AlexC 2010-11-10 12:50:58

1

您可以通过调用Thread.Suspend挂起线程。文档给出了大量的“不要这样做!”弃用警告,但我认为你是一个有效的用例。

乔恩Skeet认为you can't enumerate managed threads在正常的C#代码,虽然他暗示可能的解决方案。

+0

同意:这是一个有效的Suspend用例。 – 2010-11-10 12:47:43

+0

谢谢,尽管如此,我还是需要对所有的Thread对象进行检查,但是我找不到它的枚举器。 (Process.Threads返回一个ProcessThreads集合,而不是线程) – AlexC 2010-11-10 12:52:08

1

我假设你不会暂停全部应用程序中的线程,否则将不会有任何运行来解除它们。或者我错过了什么?

建议:尝试给你创建的所有线程提供名称。任何没有名称的线程或者与您的命名约定不匹配的线程都必须由第三方组件创建。这可能会让您的根本原因更快,而不必暂停大量线程。

+0

嗯,我需要暂停除Thread.CurrentThread之外的所有线程,然后在[插入时间到此处]休眠,然后恢复所有线程。 – AlexC 2010-11-10 12:55:14

1

从我的pov这听起来不对。

  • 你正在写哪种测试?如果您正在谈论单元测试,那么这不是单元测试案例 - 听起来更像是集成测试
  • 请考虑隔离类中的API调用,然后使用依赖注入,以便您可以在没有第三方库的情况下进行测试嘲笑/存根,也能招来/测试来自第三方库
+0

恩说。但现在可能太晚了。 – bitbonk 2010-11-10 13:16:19

+0

这不是一个单元测试或一个集成测试。我只是想要一个小应用程序来验证问题是由进入调试器引起的(并且它不是由我正在开发的软件引起的)。第三方库被包装在一个自定义的API中(正如你所建议的那样,我在我的应用程序单元测试中使用了DI),但没有任何异常从第三方库中产生,并且该错误无法通过制作再现一些特定顺序的API调用,很难看到依赖注入如何帮助这里? – AlexC 2010-11-10 13:19:08