多显示应用程序中的表单管理

发布于 2024-08-10 13:48:41 字数 1114 浏览 1 评论 0原文

我试图找出在使用双显示器的 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() 调用上阻塞主线程感觉有点混乱,但我一直无法想出更好的方法来做这个。请注意,Form1Form2 彼此独立,从不直接通信。

我考虑过使用计数信号量来等待所有显示关闭,但这与传统信号量有点相反。我不想在资源可用时执行,而是想阻塞直到返回所有资源。

关于更好的方法有什么想法吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不吻晚风 2024-08-17 13:48:41

起初我认为这会起作用:

您可以使用事件,例如:2个ManualResetEvent对象。
主线程将使用 WaitHandle.WaitAll 和一个等待事件2 个互斥体的数组。
每个线程都会获取对 1 个事件的引用,并在完成时(在其终止之前)向其发出信号。

但后来我发现你最好使用 2 个互斥锁并等待它们。
这样,如果线程在没有“发出信号”(=释放互斥体)的情况下异常终止,您将得到一个 AbandonedMutexException ,您可以并且应该处理它。您可以使用 AbandonedMutexException.MutexIndex 来了解哪个线程导致了异常。

您可以看看这个answer 查看如何处理互斥体和异常

注意:

  1. AbandonedMutexException 是新的
    .NET Framework 2.0 版。在
    以前的版本,WaitAll
    当互斥锁存在时,方法返回 true
    弃。废弃的互斥锁
    表明存在严重的编码错误。
    异常包含信息
    对于调试很有用。

  2. Windows 上不会引发异常
    98 或 Windows Millennium Edition。

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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文