.NET (C # или VB) - Как заставить Windows понять, что система не работает во время воспроизведения звука [дубликат]

Кажется, все здесь думают, что внедрение Runnable - это путь, и я действительно не согласен с ними, но есть также аргументы в пользу расширения Thread, на мой взгляд, на самом деле вы его продемонстрировали в своем коде.

Если вы реализуете Runnable, то класс, который реализует Runnable, не имеет контроля над именем потока, это вызывающий код, который может установить имя потока, например:

new Thread(myRunnable,"WhateverNameiFeelLike");

но если вы расширяете Thread, тогда вы сможете управлять этим в самом классе (как в вашем примере вы называете поток ThreadB). В этом случае вы:

A) могли бы дать ему более полезное имя для целей отладки

B) заставляют использовать это имя для всех экземпляров этого класса (если вы не проигнорируете тот факт, что он является потоком и делает с ним все, как если бы он был Runnable, но мы говорим о соглашении здесь в любом случае, поэтому можем игнорировать эту возможность, которую я чувствую).

Возможно, вы даже можете возьмите трассировку стека своего создания и используйте это как имя потока. Это может показаться странным, но в зависимости от того, как структурирован ваш код, он может быть очень полезен для целей отладки.

Это может показаться небольшим, но там, где у вас очень сложное приложение с большим количеством потоков и всего внезапные вещи «остановились» (либо по причинам тупика, либо, возможно, из-за недостатка в сетевом протоколе, который был бы менее очевидным, или других бесконечных причин), а затем получить дамп стека из Java, где все потоки называются «Thread» -1 ',' Thread-2 ',' Thread-3 'не всегда очень полезен (это зависит от того, как структурированы ваши потоки и можно ли с пользой сказать, что именно по их трассировке стека - не всегда возможно, если вы используя группы из нескольких потоков, все из которых работают с одним и тем же кодом).

Сказав, что вы, конечно же, можете сделать это выше, путем создания расширения класса потока, который устанавливает его имя в трассировку стека его создания, а затем использовать его с вашими реализациями Runnable вместо стандартный класс java Thread (см. ниже), но в дополнение к трассировке стека может быть больше контекстной информации, которая была бы полезной в имени потока для отладки (ссылка на одну из многих очередей или сокетов, которые она могла бы обрабатывать, например, в этом случае вы можете предпочесть расширить Thread специально для этого случая, чтобы вы могли заставить компилятор заставить вас (или других пользователей, использующих ваши библиотеки) передавать определенную информацию (например, указанная очередь / сокет) для использования в имени).

Вот пример общего потока с трассировкой стека вызовов как его имя:

public class DebuggableThread extends Thread {
    private static String getStackTrace(String name) {
        Throwable t= new Throwable("DebuggableThread-"+name);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(os);
        t.printStackTrace(ps);
        return os.toString();
    }

    public DebuggableThread(String name) {
        super(getStackTrace(name));
    }

    public static void main(String[] args) throws Exception {
        System.out.println(new Thread());
        System.out.println(new DebuggableThread("MainTest"));
    }
}

и вот образец выходного файла, сравнивающий два имени:

Thread[Thread-1,5,main]
Thread[java.lang.Throwable: DebuggableThread-MainTest
    at DebuggableThread.getStackTrace(DebuggableThread.java:6)
    at DebuggableThread.<init>(DebuggableThread.java:14)
    at DebuggableThread.main(DebuggableThread.java:19)
,5,main]
36
задан doncherry 16 August 2016 в 11:07
поделиться

5 ответов

Я не думаю, что есть какой-либо способ сделать это прямо в управляемом коде.

Быстрый поиск показывает этот пост от 2 лет назад. В принципе, вам нужно будет сделать какой-либо interop для вызова raw API окон.

0
ответ дан Community 19 August 2018 в 19:18
поделиться

Здесь SetThreadExecutionState реализация C #

0
ответ дан Draken 19 August 2018 в 19:18
поделиться

У вас есть несколько вариантов:

  • Используйте SetThreadExecutionState , который: Позволяет приложению сообщать системе, что он используется, тем самым предотвращая во время сна или выключении дисплея во время работы приложения. Где вы можете использовать флаг ES_SYSTEM_REQUIRED, чтобы заставить систему находиться в рабочем состоянии, сбросив таймер простоя системы.
  • Используйте SendInput , чтобы подделать нажатие клавиши, движение мыши / клики
  • . Другой альтернативой было бы изменить ваше приложение как службу Windows.

Пример SetThreadExecutionState

// Television recording is beginning. Enable away mode and prevent
// the sleep idle time-out.
SetThreadExecutionState(
    ES_CONTINUOUS | 
    ES_SYSTEM_REQUIRED | 
    ES_AWAYMODE_REQUIRED);

// Wait until recording is complete...
// Clear EXECUTION_STATE flags to disable away mode and allow the system
// to idle to sleep normally.
SetThreadExecutionState(ES_CONTINUOUS);
17
ответ дан Gustavo Mori 19 August 2018 в 19:18
поделиться

Вы должны использовать функцию SetThreadExecutionState . Что-то вроде этого:

public partial class MyWinForm: Window
{
    private uint fPreviousExecutionState;

    public Window1()
    {
        InitializeComponent();

        // Set new state to prevent system sleep
        fPreviousExecutionState = NativeMethods.SetThreadExecutionState(
            NativeMethods.ES_CONTINUOUS | NativeMethods.ES_SYSTEM_REQUIRED);
        if (fPreviousExecutionState == 0)
        {
            Console.WriteLine("SetThreadExecutionState failed. Do something here...");
            Close();
        }
    }

    protected override void OnClosed(System.EventArgs e)
    {
        base.OnClosed(e);

        // Restore previous state
        if (NativeMethods.SetThreadExecutionState(fPreviousExecutionState) == 0)
        {
            // No way to recover; already exiting
        }
    }
}

internal static class NativeMethods
{
    // Import SetThreadExecutionState Win32 API and necessary flags
    [DllImport("kernel32.dll")]
    public static extern uint SetThreadExecutionState(uint esFlags);
    public const uint ES_CONTINUOUS = 0x80000000;
    public const uint ES_SYSTEM_REQUIRED = 0x00000001;
}
32
ответ дан Joao 19 August 2018 в 19:18
поделиться
  • 1
    на некоторых компьютерах Windows XP наших клиентов NativeMethods.SetThreadExecutionState никогда не возвращает 0, никакой идеи? – Alessio 23 March 2015 в 12:52
  • 2
    @Alessio - возврат 0 означает, что метод не прошел. Из документации SetThreadExecutionState - «Если функция завершается успешно, возвращаемое значение является предыдущим состоянием выполнения потока. Если функция не работает, возвращаемое значение равно NULL. & Quot; (Примечание. Предполагаю, что вы, вероятно, уже поняли это, но хотели опубликовать ответ для полноты и помочь любому, кто мог бы прийти и просмотреть ваш комментарий) – pstrjds 14 June 2016 в 09:36
  • 3
    При попытке разрешить повторяющуюся и трудно разрешенную проблему сна с помощью Surface Pro 3, работающего под управлением Windows 8.1, я могу с ясностью заявить, что это решение, к сожалению, не работает для этой проблемы в этой ОС. – Redgum 24 August 2016 в 23:50
  • 4
    Может быть, но это, похоже, не работает в Windows 10 – ecklerpa 6 December 2017 в 20:27
  • 5
    Работал для меня в Win 10 @ecklerpa. Кроме того, если кто-то должен сделать это для видимого приложения, также не забудьте установить ES_DISPLAY_REQUIRED, чтобы избежать выключения дисплея. – Magnus Akselvoll 8 March 2018 в 08:23

Вы можете использовать SetThreadExecutionState, описанную здесь:

Поскольку это функция Win32 API, для использования его с C # вам понадобится PInvoke. Здесь описываются этапы, включая примерный метод PreventSleep для временного отключения режима ожидания:

9
ответ дан Rick Sladkey 19 August 2018 в 19:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: