Управление формой в приложении с несколькими дисплеями - PullRequest
0 голосов
/ 11 ноября 2009

Я пытаюсь найти лучший способ управления несколькими формами в приложении C #, которое использует двойные мониторы. Приложение запускается на «панели запуска», которая просто дает оператору некоторую быструю информацию и кнопку «GO». Нажатие на эту кнопку скрывает панель запуска и отображает форму на каждом мониторе в полноэкранном режиме. Я попытался захватить соответствующий код здесь:

private static List<Thread> _displays = new List<Thread>();

// "GO" button handler
private void OnClick(Object sender, EventArgs args) {
    Launch(new Form1());
    Launch(new Form2());
    WaitForAllDisplays();
}

private static void Launch(Form form) {
    Thread thread = new Thread(LaunchDisplay);
    thread.IsBackground = true;
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start(form);
    _displays.Add(thread);
}

private static void LaunchDisplay(Object obj) {
    Form display = obj as Form;
    // [snip] logic to place form on correct monitor [/snip]
    display.ShowDialog();
}

public static void WaitForAllDisplays() {
    foreach (Thread thread in _displays) {
        thread.Join();
    }
}

Мне кажется немного грязным оставлять основной поток заблокированным на этом вызове WaitForAllDisplays(), но я не смог придумать лучшего способа сделать это. Обратите внимание, что Form1 и Form2 не зависят друг от друга и никогда не общаются напрямую.

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

Есть мысли о лучшем подходе?

1 Ответ

1 голос
/ 11 ноября 2009

Сначала я подумал, что это сработает:

Вы можете использовать События, например: 2 объекта ManualResetEvent. Основной поток будет ожидать событий, используя WaitHandle.WaitAll и массив из 2 мьютексов. Каждый поток получает ссылку на 1 событие и сигнализирует об этом, когда он завершен (до того, как он умирает).

Но тогда я понял, вам лучше использовать 2 мьютекса и ждать их. Таким образом, если поток ненормально завершается без «сигнализации» (= освобождение мьютекса), вы получите исключение AbandonedMutexException, которое вы можете и должны обрабатывать. Вы можете использовать AbandonedMutexException.MutexIndex, чтобы узнать, какой поток вызвал исключение.

Вы можете взглянуть на этот ответ , чтобы узнать, как обрабатывать мьютекс и исключение

Примечание:

  1. AbandonedMutexException является новым в .NET Framework версия 2.0. В предыдущие версии, WaitAll Метод возвращает истину, когда мьютекс отказались. Заброшенный мьютекс указывает на серьезную ошибку кодирования. Исключение содержит информацию полезно для отладки.
  2. Это исключение не выдается на Windows 98 или Windows Millennium Edition.
...