Спать все потоки в программе, кроме текущего/основного в С#

Главный вопрос: как усыпить все потоки, работающие в программе, кроме текущего/основного?

У меня есть программа с использованием подключения к MS SQL Server через EF, проблема в том, что иногда, когда программа работает, она зависает, когда мы переводим компьютер в спящий режим и просыпаемся, проблема, похоже, связана с подключением к БД. Программа может попытаться получить некоторые данные из БД, когда соединение еще не восстановлено. Идея заключалась в том, чтобы обнаружить событие PowerModeChanged, и когда мы обнаружим режим Suspend, все потоки, кроме текущего, должны быть переведены в спящий режим до следующего события Resume. Я не знаю, как усыпить или программно приостановить работу разных потоков, отличных от текущего. Я нашел это:

ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

но я не нахожу правильного способа разыграть его или найти их по идентификатору и не смогу их усыпить.

Есть какой-либо способ сделать это?

P.S. Еще немного кода ниже (функция SystemEvents_PowerModeChanged, еще незавершенная):

[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
                    }
                }
            }
        }

person witkowski01    schedule 28.11.2017    source источник
comment
Это не дубликат, у меня нет списка этих тредов, я должен создать один, и я не хочу ждать в одном треде второго. Мне нужно каким-то образом получить список активных потоков, перевести их в спящий режим и проснуться при запуске события.   -  person witkowski01    schedule 28.11.2017
comment
хорошо, когда ты говоришь   -  person Hille    schedule 28.11.2017
comment
Откуда вы знаете, что Resume не произойдет до восстановления соединения?   -  person bornfromanegg    schedule 28.11.2017
comment
Я нет, я даю ему несколько секунд, и после этого, когда у меня не будет соединения, я помещу там приятную информацию, что, если вы хотите продолжить, вы должны восстановить соединение и нажать кнопку «Повторить попытку» или закрыть приложение.   -  person witkowski01    schedule 28.11.2017
comment
Похоже на проблему XY...   -  person Roger Lipscombe    schedule 28.11.2017
comment
проблема, похоже, связана с подключением к БД. Я бы сказал, что ваш первый шаг должен состоять в том, чтобы выяснить, верно ли это предположение. В противном случае вы можете приложить усилия для решения проблемы, которой на самом деле у вас нет.   -  person Fildor    schedule 28.11.2017


Ответы (1)


Я думаю, что это неправильный подход. Сами ваши потоки должны реагировать на эти системные события и действовать соответственно.

Приостанавливать и возобновлять их из другого потока опасно. У вас нет абсолютно никакого контроля над кодом, который эти потоки выполняют в данный момент, или над тем, будет ли он по-прежнему работать правильно, когда они снова возобновятся.

Это одна из причин, почему Thread.Suspend() и Thread.Resume() устарели и больше не должны использоваться.


Измените свои рабочие потоки, чтобы они сами обнаруживали события питания и могли действовать соответствующим образом: переходить в определенное состояние и снова начинать работу при возобновлении питания. Или завершите и полностью перезапустите позже.

person René Vogt    schedule 28.11.2017
comment
То же. См. также здесь. Вы можете реализовать что-то похожее на CancellationToken, но с приостановкой, а не отменой. - person bornfromanegg; 28.11.2017
comment
@witkowski01 Thread.Sleep() приостанавливает вызывающий его поток. Вы не можете отправить другой поток в спящий режим с этим вызовом. И если ваши рабочие потоки используют Thread.Sleep(), то, по крайней мере, вы знаете, в какой момент кода они приостанавливают себя, но у вас нет хорошего метода, чтобы разбудить их снова. - person René Vogt; 28.11.2017
comment
Итак, нет правильного способа сделать то, чего я хочу добиться, вместо того, чтобы переписывать кучу кода, чтобы добавить событие PowerMode во все места, когда мне нужно его использовать? - person witkowski01; 28.11.2017
comment
@ witkowski01 Мне жаль, что у меня нет лучшего ответа. Я опубликовал это только как ответ, потому что это слишком долго для комментария. Но я просто говорю, что сам этот подход плох (хотя вы можете использовать Suspend и Resume, но вы действительно не должны, и я думаю, что результаты будут не такими, как вы ожидаете). Как наиболее эффективно решить вашу проблему, зависит от вашего реального кода. - person René Vogt; 28.11.2017
comment
Спасибо за ваше время и ответы. - person witkowski01; 28.11.2017