开发者

Pausing all threads in current process at run time

I have a bug in my app that seems to show it's face only when I pause the app in the debugger for a few minutes. I suspect this is due to a third party networking library I am using having a heartbeat thread, which becomes disconnected when it can not ping the server while it's heartbeat thread is paused.

I am trying to write a test case app for this to verify that this is the cause of the bug. To do so, I need a way to pause all the threads in the app (which i will later narrow down to pausing only the thread I suspect may be the heartbeat thread) to simulate pausing the app in the debugger.

Does anyone know how to do this? Is it even possible for one thread to cause another to sleep?

Thanks, Alex

UPDATE:

I ended up deciding that I didn't really need an app to do this for me, seeing as the point was just to verify that pausing in the debugger was causing the disconnect. So, here's what I did... (The simplest ways are often the best... or at least the simplest...)

    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.开发者_如何学JAVAReadLine();
    }

And the output:

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!


You can use this to quickly indentify the threads of your process:

using System.Diagnostics;

ProcessThreadCollection threads = Process.GetCurrentProcess().Threads;

Then you can use kernel32.dll with P/Invoke to do whatever you need with those threads. Use OpenThread to get a handle to the desired thread and then suspend it with SuspendThread using that handle.

Here are the P/Invoke declaration for the two methods:

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

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


I assume you're not going to pause all the threads in the application, otherwise there will be nothing running to un-suspend them. Or have I missed something?

A suggestion: Try giving names to all the threads you create. Any threads without a name, or that don't match your naming convention, must have been create by a third-party component. This might get you to the root cause quicker without having to pause lots of threads.


From my pov this sounds not right.

  • Which kind of tests are you writing? If you are speaking about unit tests, then this is not a Unit test case - sounds more like integration test
  • Consider to isolate the API calls in a class and then use dependendcy injection so that you can test without the 3rd party library with mocks/stubs and can also provoke/test an exception raised from the 3rd party library


You can suspend threads by calling Thread.Suspend. The documentation gives big "DON'T DO THIS!" deprecation warnings, but I think yours is a valid use case.

Jon Skeet thinks you can't enumerate managed threads in normal C# code, though he does hint at a possible solution.


You could call the Thread.Suspend then Thread.Resume methods but those are deprecated and is not recommneded to use them.

But you can do the following: Have a boolean flag that when set you put your thread on a big sleep. OR Better to use ManualResetEvent.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜