Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

Windows Forms いつも脳死で Program.cs に実装している内容

0
Posted at

はじめに

PC から 2 年半くらい前に投稿した記事を発掘したので、再 UP です。

改訂履歴

  • 2026/08/04 : 再投稿。
  • 2024/03/14 : 初版公開。

本文

1. 環境

  • .NET Framework 4.8.1
  • Visual Studio Community 2022

2. 実装

例外捕捉時、メッセージを表示していますが、実際はログ出力にすることが多いです。

Program.cs
using System;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace App
{
    /// <summary>
    /// アプリケーションのエントリーポイントを定義します。
    /// </summary>
    internal static class Program
    {
        /// <summary>
        /// アプリケーションのメインエントリポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.ThreadException += Application_ThreadException;
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            var mutex = new Mutex(true, Application.ProductName, out bool createdNew);

            try
            {
                if (!createdNew)
                {
                    MessageBox.Show(
                        text: "このアプリケーションは既に起動中です。",
                        caption: "Error",
                        buttons: MessageBoxButtons.OK,
                        icon: MessageBoxIcon.Error);

                    return;
                }

                Application.Run(new SampleForm());
            }
            finally
            {
                if (createdNew)
                {
                    mutex.ReleaseMutex();
                }

                mutex.Close();
            }
        }

        /// <summary>
        /// UI スレッドで発生した未処理の例外を処理します。
        /// </summary>
        private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            var text = new StringBuilder();
            text.AppendLine(e.Exception.Message);
            text.AppendLine("スタックトレース:");
            text.AppendLine(e.Exception.StackTrace);

            MessageBox.Show(
                text: text.ToString(),
                caption: "Error",
                buttons: MessageBoxButtons.OK,
                icon: MessageBoxIcon.Error);
        }
    }
}

3. 動作確認

動作確認用の画面を作成したので、実際に確認していきます。なお、二重起動の防止処理については今回は省略します。

SampleForm.cs
using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace App
{
    public partial class SampleForm : Form
    {
        public SampleForm() => InitializeComponent();

        // UI スレッドで例外
        private void ThrowExceptionButton_Click(object sender, EventArgs e)
            => int.Parse(null);

        // async/await で例外
        private async void AwaitTaskRunButton_Click(object sender, EventArgs e)
            => await Task.Run(() => int.Parse(null));

        // Task.Wait() で例外
        private void TaskRunWaitButton_Click(object sender, EventArgs e)
            => Task.Run(() => int.Parse("Hoge")).Wait();

        // Task.Run() で例外
        private void TaskRunButton_Click(object sender, EventArgs e)
            => Task.Run(() => int.Parse("2147483648"));
    }
}

見せる意味はないですが、一応画面はこんな感じです。

3-1. UI スレッドでの例外発生

未処理の例外を捕捉できていて良い感じです。

3-2. サブスレッドでの例外発生 - await

こちらも良い感じです。

3-3. サブスレッドでの例外発生 - Wait()

これは良い感じのように見えて、例外メッセージがおかしいですね。「1 つ以上のエラーが発生しました。」と表示されており、どの例外を捕捉したのか分かりません。

これは Task.Wait() を使用した場合、複数の例外が AggregateException にまとめられる仕様のためです。詳細は下記の記事をご覧ください(丸投げ)。

個人的にはそもそも開発時に Task.Wait()Task.Result の使用を非推奨(というか基本的に禁止)にしているため、今回このケースには対応していません...!非推奨の理由は下記の MSDN 参照です(丸投げ)。

async/await を使ってください...!

3-4. サブスレッドでの例外発生 - 待たない場合

このケースでは、そもそも例外を捕捉できません。待たない場合は下記のように try catch で囲んでも捕捉できません...。

SampleForm.cs
private void TaskRunButton_Click(object sender, EventArgs e)
{
    try
    {
        Task.Run(() => int.Parse("2147483648"));
    }
    catch (Exception ex)
    {
        // ※ ここには入ってこない。
        MessageBox.Show(ex.ToString());
    }
}

おわりに

当時の僕曰く「コピペ用にサクッと書き切るつもりが、非同期処理の例外関連で分量が多くなりました。調べ物が少し大変でしたが、勉強になったのでよかったです...!」とのことです。がんばれ、僕。

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?