출처 : http://stackoverflow.com/questions/1584062/how-to-wait-for-thread-to-finish-with-net#2228508




2016/11/21 - [프로그램 자료/Visual C#] - Winform에서 작업하는 동안 로딩화면 띄우기





쓰레드 구현시, 완료 이벤트를 받고 싶었다. 


우선 아래의 클래스를 작성해 넣는다. 



스톱 기능을 추가해보았다

using System;

using System.Threading;

 

public class ThreadWorker

{

    Thread th;

    public event EventHandler DoWork;

    public event EventHandler OnCompleted;

 

    public event ProcessChangedEventHandler OnProcessChanged;

    public delegate void ProcessChangedEventHandler(object sender, ProgressEventArgs e);

 

    public void Stop()

    {

        th.Abort();

    }

 

    public void ReportProgress(float per)

    {

        if (OnProcessChanged != null)

            OnProcessChanged(this, new ProgressEventArgs(per));

    }

 

    public void Run()

    {

        th = new Thread(Work);

        th.IsBackground = true;

        th.Start();

    }

 

    private void Work()

    {

        if (DoWork != null)

            DoWork(this, EventArgs.Empty);

 

        if (OnCompleted != null)

            OnCompleted(this, EventArgs.Empty);

    }

}

public class ProgressEventArgs : EventArgs

{

    public ProgressEventArgs(float percent)

    {

        this.Percent = percent;

    }

 

    public float Percent { get; private set; }

}

 



위의 클래스를 가지고 예제를 꾸려보면 아래와 같다.


static ThreadWorker tw = new ThreadWorker();

tw.DoWork += Tw_DoWork;

tw.OnCompleted += Tw_OnCompleted;

tw.OnProcessChanged += Tw_OnProcessChanged;


delegate void ChangePercentDelegate(float per); //percent 델리게이트

 

private void Tw_OnCompleted(object sender, EventArgs e)

{

    // 작업완료

}

private void Tw_DoWork(object sender, EventArgs e)

{

    SearchFile(sender); //파일 검색 시작

}

private void Tw_OnProcessChanged(object sender, ProgressEventArgs e)

{

    ChangePercentDele(e.Percent); // 퍼센트를 주기위한 이벤트 등록

}

private void ChangePercentDele(float per)

{

    //실제 퍼센트를 화면상에서 올리는 곳

    if (statusStrip1.InvokeRequired)

    {

        statusStrip1.Invoke(new ChangePercentDelegate(ChangePercent), new object[] { per });

    }

    else

        ChangePercent(per);

}

private void ChangePercent(float per)

{

    txtPercent.Text = (per * 100).ToString("#,###.00") + "%";

}

private void btnCancel_Click(object sender, EventArgs e)

{

    // 쓰레드 종료인데 쓰레드 생성을 많이해서(Parallel.ForEach)

    isStop = true;

    Thread.Sleep(1000);

    tw.Stop();

    ControlState(false);

}

 

private void SearchFile(object sender)

{

    // 실제 파일 찾는 부분

    Stopwatch sw = new Stopwatch();

    sw.Start();

 

    Parallel.ForEach(fileList, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, (file, stateFile) =>

    {

        curFile++;

        if (curFile % 10 == 0)

            tw.ReportProgress((float)curFile / (float)totalFile); //퍼센트 보고

 

    });

    tw.ReportProgress((float)1);

    sw.Stop();

    Console.WriteLine("검색종료 : " + sw.ElapsedMilliseconds);

}

 











이전버전


class ThreadWorker

{

    public Func<int> Process { getset; } // 실제 스레드가 작업할 메소드 

    public event EventHandler OnCompleted; // 작업할 내용르

 

    public void Run()

    {

        Process();

       

        if (OnCompleted != null)

            OnCompleted(thisEventArgs.Empty);

    }

}






사용방법은 아래와 같다.



private void button1_Click(object sender, EventArgs e)

{

    ThreadWorker worker = new ThreadWorker();

    worker.Process = proc;

    worker.OnCompleted += new EventHandler(Complete);

 

    Thread thread1 = new Thread(worker.Run);

    thread1.Start();

 

}

private int proc()

{

    for (int i = 0; i < 5000; i++)

    {

        Console.WriteLine(i);

    }

    return 0;

}

 

private void Complete(object sender, EventArgs e)

{

    MessageBox.Show("complete");

}






















Posted by motolies
,