본문 바로가기

[C#] 싱글턴 패턴을 사용한 ProgressPopup만들기

I'm 영서 2022. 7. 8.
반응형

프로그램을 만들며 ProgressPopup을 만들어야 할 필요가 있다.

무거운 작업을 한다거나 오래 걸리는 작업을 할 때 보통 돌아가고 있는 것을 보여주기 위해 쓴다고 생각하는데

이때  무거운 작업은 백그라운드 Thread로 돌리는데 이때 메인폼의 작업을 멈추기 위해 Thread를 추가해야 했다..

 

Thread는 Thread t = new... 말고 BackgroundWorker를 사용했다.

기본적으로 백그라운드에서 작업하는 백그라운드 Thread이며 사용이 매우 편리하여 유용하다.. 

 

 

BackGounrdWorker는

Dowork라는 Thread t = new Thread( () => Method) 를 대신해주는 EventHandler와

CompleteWork 라는 Thread 작업이 완료 되었을 때 실행할 작업을 정의 할 수있다.

 

문제는 Popup은 Showdialog로 열것이기 때문에.. (메인폼의 조작을 막는것보다 훨씬 간단하므로) 

Popup을 열때 쓰레드와 닫을때 Thread가 다르므로 문제가 생긴다.

 

나는 Utils라는 클래스 라이브러리를 따로 추가하여 그곳에서 Popup을 호출하도록 작성하였다. ( 어떤 프로젝트가 추가되더라도 Utils만 참조하여 Popup을 부를 수 있도록..)

 

길게 작성했는데 한문장으로 작성하면

멀티쓰레드 환경에서 안정적으로 리소스를 생성하기 위해 싱글톤 방식을 사용한것.

 

아무튼 Winfrom에 DevExpress를 사용하여 작성했고. 실제로 Devexpress를 사용하지 않으면 ProgressPanel 만 없고 progressBar는 그대로 작동한다.

 

public sealed partial class myProgressBar : DevExpress.XtraEditors.XtraForm
{
    private myProgressBar()
    {
        this.InitializeComponent();
    }

    private static readonly Lazy<myProgressBar> _instance = new Lazy<myProgressBar>(() => new fncProgressBar());

    public static myProgressBar getInstance { get { return _instance.Value; } }

    private void myProgressBar_FormClosing(object sender, FormClosingEventArgs e)
    {
        this.Hide();
        e.Cancel = true;
    }   
}

Lazy<T> 는 지연생성이라는 개념이라고 보면 되는데

선언 즉시 생성이 아니라 접근할때 생성해주는 것이다...

 

Lazy 관련된 내용은 간단히 주의사항만 작성하자면  멀티 Thread 환경에서의 생성은 안정성을 보장하나 그 후의 Thread참조에서는 문제가 발생할 수 있다는것을 확실히 알아야 한다..

 

위의 싱글턴 예제는 간단한 방식으로 FormClosing을 추가한 이유는 Form.Close의 경우 객체를 지워주는데 다시 생성하기보다는 생성된 팝업을 그냥 안보여주고 Task바에도 안보이게 해주는게 간단했기 때문..

 

이렇게 하면 BackgroundWorker에서 DoWork메서드를 Run하고 Popup을 실행시키게 되는데  Showdialog()로 Popup을 오픈했기 때문에 MainForm의 조작은 막고 무거운 작업은 DoWork 쓰레드에서 실행하게 된다.

 

그리고 DoWrok에서 UpdatePopup을 통해 ProgressBar를 업데이트 시켜주면 아주 간단하게 작업상황에 대한 ProgressBar를 얻을 수 있다.

 

마지막으로 CompleteWork에서 팝업을 닫기(실제로는 Hide)를 해주면 FormClosing이 실행되고 MainForm의 조작은 가능해지며 popup은 사라지게 된다..

 

반응형

댓글