0

Main question is: how to sleep all threads running in program except current/main one?

I have program with use connection to MS SQL Server via EF, the problem is that sometimes when program is running it crush when we put computer to sleep mode and wake up, problem seems to be connection to DB. Program may try to get some data from DB when connection is not yet recovered. Idea was to detect event of PowerModeChanged and when we detect Suspend mode all threads except current should be put into sleep till the next event Resume. I do not know how to put to sleep or programmatically hold work of different threads than current one. I found this:

ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

but I do not find correct way to cast it, or find them by Id, and be able to put them to sleep.

Is there any way to do this?

P.S. Some more code bellow (SystemEvents_PowerModeChanged function, unfinished yet):

[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
public static extern Int32 GetCurrentWin32ThreadId();
        private void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e)
        {
            if (e.Mode == PowerModes.Suspend)
            {
               ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

                int currentThreadId = GetCurrentWin32ThreadId();
                Console.WriteLine("CURRENT thread: " + currentThreadId);

                foreach (ProcessThread thread in currentThreads)
                {
                    if (thread.Id != currentThreadId)
                    {
                        Console.WriteLine("Disable thread: " + thread.Id);
                        // Disable threads
                    }
                }
            }
            else if (e.Mode == PowerModes.Resume)
            {
                ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;
                int currentThreadId = GetCurrentWin32ThreadId();
                Console.WriteLine("CURRENT thread: " + currentThreadId);
                foreach (ProcessThread thread in currentThreads)
                {
                    if (thread.Id != currentThreadId)
                    {
                        Console.WriteLine("Enable thread: " + thread.Id);
                        // Enable threads
                    }
                }
            }
        }
  • This is not duplicate, I do not have list of this threads, I have to make one, and I do not want to wait in one thread for second one. I need to get somehow list of active threads, put them to sleep, and wake up when event fired up. – witkowski01 Nov 28 '17 at 14:17
  • ok when you say – Hille Nov 28 '17 at 14:18
  • How do you know that `Resume` won't occur before the connection is recovered? – bornfromanegg Nov 28 '17 at 14:20
  • I don't, I give it few seconds, and after that, when I will not have connection, I will put there nice information, that if you wana continue you should recovery connection and press button try again, or close app. – witkowski01 Nov 28 '17 at 14:27
  • 2
    Sounds like an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)... – Roger Lipscombe Nov 28 '17 at 14:29
  • _"problem **seems** to be connection to DB"_ - I would say your first step should be to find out if that assumption is correct. Otherwise you may put effort in solving a problem you do not actually have. – Fildor Nov 28 '17 at 15:38

1 Answers1

2

I think this is the wrong approach. Your threads themselves should react on those system events and act accordingly.

To suspend and resume them from another thread is dangerous. You have absolutly no control over the code those threads are currently executing, or if this will still work correctly when they get resumed again.

That's one of the reasons why Thread.Suspend() and Thread.Resume() are deprecated and should no longer be used.


Change your working threads so that they detect the power events themself and can act accordingly: go into a defined state and start work again when power is resumed. Or terminate and get completely restartet later.

René Vogt
  • 43,056
  • 14
  • 77
  • 99
  • Ditto. See also [here](https://stackoverflow.com/questions/1058126/force-a-different-thread-to-sleep). You could implement something akin to a `CancellationToken`, but one that suspends instead of cancels. – bornfromanegg Nov 28 '17 at 14:30
  • @witkowski01 `Thread.Sleep()` suspends the thread that calls it. You cannot send a different thread to sleep with that call. And if your working threads use `Thread.Sleep()`, then at least you know at which point in code they suspend themselves, but you lack a good method to wake them up again. – René Vogt Nov 28 '17 at 14:32
  • So there is no proper way to do that what I want to achieve, instead of rewrite bunch of code to add PowerMode event to all places when i need to use it? – witkowski01 Nov 28 '17 at 14:38
  • @witkowski01 I'm sorry to have no better answer. I only posted this as answer because it's too long for a comment. But I'm just saying that this very approach is bad (though you _can_ use `Suspend` and `Resume`, but you really shouldn't and I guess the results won't be what you expect). How to solve your problem most efficiently depends on your real code. – René Vogt Nov 28 '17 at 14:43
  • Thank you for your time and answers. – witkowski01 Nov 28 '17 at 14:44