본문 바로가기
코딩취미/C,C++

[C#] 멀티스레드(MTA) 환경에서 프로그램 재시작하는 방법

by 브링블링 2023. 12. 20.
반응형

멀티스레드(MTA) 환경에서 프로그램 재시작하는 방법

GUI 프로그램을 만들면서, 프로그램을 재시작해야할 경우가 생겼습니다. 특정 버튼을 클릭하면, 다른 exe 프로그램을 실행시키고 이후에 다시 본래의 s/w를 시작하는 과정이 필요했는데, 이런 과정에서 필요했던 내용들입니다.

멀티스레드에서 재시작하는 경우:

특징:

  1. 다른 스레드에서 프로그램을 재시작할 때, 메인(UI) 스레드와 다른 작업 스레드 간의 동기화에 주의해야 합니다.
  2. 프로그램을 재시작하는 동안 다른 스레드에서 실행 중인 작업이 영향을 받을 수 있습니다.
  3. UI 스레드와 작업 스레드 간의 통신 및 동기화 문제를 고려해야 합니다.

차이점:

  1. 멀티스레드에서 프로그램을 재시작하면, UI 갱신 및 다른 스레드 간의 동기화 문제로 복잡성이 증가합니다.
  2. 다른 스레드에서 UI를 조작할 때는 Dispatcher 등을 사용하여 UI 스레드와 통신해야 합니다.
using System;
using System.Threading;
using System.Windows.Forms;

namespace RestartMultithreadedApplication
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // UI를 담당하는 메인 스레드 시작
            Thread uiThread = new Thread(() =>
            {
                Application.Run(new MainForm());
            });

            // UI 스레드 시작
            uiThread.Start();
        }
    }
}

 

단일 스레드에서 재시작하는 경우:

특징:

  1. 단일 스레드 환경에서는 스레드 간 동기화 문제가 적어집니다.
  2. 프로그램을 재시작하는 동안 다른 스레드로부터 영향을 받지 않습니다.

차이점:

  1. 스레드 간 동기화 문제가 적어 복잡성이 감소하지만, 그렇다고 해서 모든 상황에서 적합한 것은 아닙니다.
  2. 단일 스레드에서 UI 갱신을 위해 특별한 처리 없이 UI를 조작할 수 있습니다.
using System;
using System.Windows.Forms;

namespace RestartSingleThreadedApplication
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // UI를 담당하는 메인 스레드 시작
            Application.Run(new MainForm());
        }
    }
}
반응형

C# 멀티스레드로 구성된 GUI에서 버튼 클릭했을 때 프로그램 재시작

C#에서 멀티스레드로 구성된 GUI에서 버튼을 클릭했을 때 프로그램을 재시작하는 코드를 작성하려면 주의해야 할 사항이 있습니다. 일반적으로 UI 조작은 메인 스레드에서 이루어져야 하므로, 새로운 스레드에서 프로그램을 재시작해야 하는 경우에는 메인 스레드로 전환해야 합니다.

 

아래는 C#의 WPF를 사용한 간단한 예제 코드입니다. 코드에서는 Dispatcher.Invoke를 사용하여 메인 스레드에서 UI 조작을 수행하고, Thread를 사용하여 새로운 스레드에서 프로그램을 재시작합니다.

using System;
using System.Threading;
using System.Windows;

namespace RestartMultithreadedApplication
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            InitializeUI();
        }

        private void InitializeUI()
        {
            Button restartButton = new Button();
            restartButton.Content = "Restart";
            restartButton.Click += RestartButton_Click;

            StackPanel stackPanel = new StackPanel();
            stackPanel.Children.Add(restartButton);

            Content = stackPanel;
        }

        private void RestartButton_Click(object sender, RoutedEventArgs e)
        {
            // 새로운 스레드에서 프로그램을 재시작
            Thread restartThread = new Thread(() =>
            {
                // UI 조작을 메인 스레드에서 수행
                Application.Current.Dispatcher.Invoke(() =>
                {
                    RestartApplication();
                });
            });

            // 스레드 시작
            restartThread.Start();
        }

        private void RestartApplication()
        {
            // 여기에서 프로그램을 재시작하는 로직을 구현
            MessageBox.Show("Restarting the application...");

            // 실제로는 새 프로세스를 시작하거나 현재 프로세스를 종료하고 다시 시작하는 등의 작업이 필요
            // (이전의 예제 코드 참고)
        }
    }
}

이 코드에서는 RestartButton_Click 메서드에서 새로운 스레드를 생성하고, 그 스레드에서 RestartApplication 메서드를 호출하고 있습니다. RestartApplication 메서드에서는 UI 조작을 메인 스레드에서 수행하도록 Dispatcher.Invoke를 사용하고, 이곳에서 프로그램을 재시작하는 로직을 구현할 수 있습니다.

 

실제 구현했던 방법

재시작하는 함수 RestartApplicationMTA()를 만들어서 사용했습니다.

 

버튼 이벤트가 발생하면, 이전 설정에 따라서 첫번째 동작인지 확인해서 시나리오별로 동작시작.

        private void RB_btnFlash_Click(object sender, EventArgs e)
        {

            if (RB_cbSelectIC.TextBoxText == "select")
            {
                event_btnFlash();
            }
            else
            {
                HIDSetI2C(false);

                if (File.Exists(flagFilePath) == false)
                {
                    File.Create(flagFilePath).Close();
                    RestartApplicationInMTA();
                }
                else
                {
                    RestartApplicationInMTA();
                }
            }
        }
        
       
         private void RestartApplicationInMTA()
        {
            // 현재 응용프로그램 경로
            string exePath = System.Windows.Forms.Application.ExecutablePath;

            // 새로운 프로세스 시작 (MTA 스레드로)
            Process.Start(new ProcessStartInfo
            {
                FileName = exePath,
                UseShellExecute = true,
                CreateNoWindow = false
            });
            
            // 현재 응용프로그램 종료
            System.Windows.Forms.Application.Exit();
        }

 

프로그램이 재시작됐는지 확인하는것은, 플래그 파일이 생성유무로 판단했습니다.

        private void MainForm_Shown(object sender, EventArgs e)
        {
            ...

            if (File.Exists(flagFilePath))
            {
                File.Delete(flagFilePath);
                event_btnFlash();
            }

        }

 

반응형