简体   繁体   中英

Form management in a multi-display application

I'm trying to figure out the best way to manage multiple forms in a C# application that uses dual-monitors. The application starts to a "launchpad," which just gives the operator some quick information and a "GO" button. Pressing that button hides the launchpad and displays a form on each monitor in full-screen. I've tried to capture the relevant code here:

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();
    }
}

It feels a little messy to leave the main thread blocked on this WaitForAllDisplays() call, but I haven't been able to think of a better way to do this. Notice that Form1 and Form2 are independent of each other and never communicate directly.

I considered using a counting semaphore to wait for all displays to close, but this is a little opposite of a traditional semaphore. Instead of executing when a resource becomes available, I want to block until all resources are returned.

Any thoughts on a better approach?

At first I thought of this would work:

You can use Events for example: 2 ManualResetEvent objects. The main thread will wait on the events using WaitHandle.WaitAll and an array of 2 Mutexes. Each thread gets a reference to 1 event and signals it when it's done (before it dies).

But then I figured you're better off using 2 mutexes instead and waiting on them. This way if a thread is terminated abnormally without "signalling" (=Releasing the mutex) you'll get a AbandonedMutexException which you can and should handle. You can use AbandonedMutexException.MutexIndex to know which thread caused the exception.

You can have a look at this answer to see how to handle the mutex and exception

NOTE:

  1. AbandonedMutexException is new in the .NET Framework version 2.0. In previous versions, the WaitAll method returns true when a mutex is abandoned. An abandoned mutex indicates a serious coding error. The exception contains information useful for debugging.
  2. This exception is not thrown on Windows 98 or Windows Millennium Edition.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM