PROGRAMMING WORKSHOP

.Net FrameWork,VB.Net | BackgroundWorker,Thread

BackgroudWorker콘트롤...

윈도우 폼에서 어떤 버튼 콘트롤을 실행하면
해당 작업이 끝나기 전까지는 다른 작업을 할수 없다
이것을 Thread라고 한다
하나의 일련의 작업이 시작되면 이 작업이 끝날때까지 다른 작업이 치고 들어 올수 없다
윈도우의 모든 콘트롤은 기본적으로 하나의 Thread로 운용된다
하나의 작업이 끝날때까지 다른 작업을 못하면 멍청히 쳐다만 보고 있어야 한다
하나의 작업을 하면서 다른 작업을 하려면,
Thread를 하나더 만들고(이것은 나중에 이야기 하고)어쩌구 하여야 하는
번거로움이 있다
이것을 도와주는 컨트롤이 BackgroundWorker라는 것이다
이것을 알아보도록 하자

그야 말로 Background...뒤에서 worker 일하는 일꾼이다
무슨 소린지 해보는 것이 좋겠지
아래의 그림과 같이



ProgressBar콘트롤을 하나 달고
하나의 버튼은 BackgroundWorker컨트로를 사용하고
다른 버튼 하나는 일반적인 방법으로 실행하여 비교 해보면..
아하~...이런 것이로구나..
이것을 꼭 하고 싶었었는데 하게 되는 컨트롤이다
하나의 작업을 하는데 무지하게 시간이 걸리는 것이라면
웹에서 큰화일을 다운 받는다거나, 사이즈가 큰 이미지작업을 한다거나
사용자가 넋놓고 기다리게 하는 것은 좋은 일이 아니다
이런 경우는 필수적으로 사용할 일이다
개념을 좀더 그림으로 표현하자면



세상의 일과 비슷하게 하려고 노력하는 것이 컴퓨터 프로그래밍이다
어떤 일을 협력업체(BackgroundWorker)에게 주고
그 시간에 다른 작업을 할수 있게 하는 셈이다

VBA에서 DoEvents 명령어가 생각나시면 좋겠다
실행을 하면서 순간순간 다른 작업을 할수 있도록 치고 들어오게 하는 명령
좀 효율이 떨어지는 작업이지만,이런 개념을 흉내낸 셈이다

이것은 하나의 Thread에서 작업하는 것도 별도의 다른 Thread를 만드는 작업을
BackgroundWorker가 대신해 주는 것이다
물론 Thread 개체를 사용하여 BackgroundWorker콘트롤이 하는
일을 직접 코딩할수도 있다

***[LOG-IN]***

Threading.Thread,Lambda Expression,Invoke,AddressOf

BackgroundWorker 컨트롤 대신에 Thread개체를 사용하여 만들어 보도록 하자
BackgorundWorker 컨트롤이 없다면 Thread 개체를 사용하면 되는 것
그러니 BackgroundWorker이던의 Thread개체를 이해하고 활용하여야 한다

Thread 개체(크래스)는
Threading 이라는 NameSpace의 Thread 개체이다
Dim oQ As New Threading.Tread() 로 생성하여 사용한다
이것을 만든다고 하는 것은 현재 Main Thread외의 새로운 작업라인을
만든다는 이야기다
Main Thread의 작업과 상관없이 별도의 작업라인이 만들어지니..
Main작업에서 하는 작업에 아무 지장없이 안보이는 곳에서 새로운 작업을
병행하게 하는 것


''전역변수로 Tread 개체변수를 준비하고
Dim oMyThread As Threading.Thread
''버튼을 크릭하면 새로운 Thread를 만들어서 일을 시킨다
''본래의 다른 작업에는 지장없이 뒤에서 새로운 Thread에서 시킨일을 열심히하게 된다
Private Sub ButtonRunAsynchronous_Click(sender As System.Object, e As System.EventArgs) Handles ButtonRunAsynchronous.Click
''Thread개체를 생성할때, 어떤일을 할지 프로시져를 지정해준다
''이때 사용하는 연산자가 AddressOf 
        oMyThread = New Threading.Thread(AddressOf doBackGroundWork)
''생성한 Thread의 일이 시작된다		
        oMyThread.Start()
		
        Me.ButtonStopProcess.Enabled = True
 End Sub
 
''Thread가 시작되면서 실행되는 프로시져 
 Sub  doBackGroundWork()
	For iX As Integer = 0 To 100
''시작을 늦추기 위하여 Thread의 Sleep
		Threading.Thread.Sleep(100)
''요기서 중요한 부분이다..
''폼에 그려진 모든 컨트롤들은 호출하여 실행되는 별개의 Thread에서는 접근할수 없다
''창구에서 다른 창구의 일을 간섭할수 없는 것과 같다
''별도의 창구에 서있는 사람에게 일을 시키려면 Invoke 메소드를 사용한다
''이때 매개변수로 사용하는 것이 Lambda expression 이라고 하는 것
''이것은 프로시져를 표현식으로 표현하는 것
''나중에 다른 주제에서 더 설명하게 된다..
''Lambda Expression은 Delegate라는 것(이것도 다른 주제에서 다루자)을
''간편하게 실행하는 표현이다
		Invoke(Sub() Me.ProgressBar1.Value = iX)
		Invoke(Sub() Me.Text = "Processing......" + ProgressBar1.Value.ToString() + "%")
	Next
	Invoke(Sub() Me.ButtonDoSomething.Enabled = True)
End Sub
 

아래와 같이 Inline에서 프로시져를 실행하도록 표현하는 것을 Lambda Expression이라고 하고
앞으로 자주 활용하게 될 것이다
그리고 반드시 익숙하게 알아야 보다 쎄련된 프로그래밍을 할수 있다

Invoke(Sub() Me.ButtonDoSomething.Enabled = True) 섭프로시져는 물론 함수도 이렇게 사용한다
함수나 프로시져의 이름은 필요없는 셈이다
이것은 다음 페이지에서 이야기 할 Delegate타입을 받는 매개변수에서 항상 사용할수 있다
즉 위의 Invoke함수는 매개변수로 Delegate타입을 매개변수로 받는 것이고
Delegate타입개체가 필요한 곳에 Lambda Expression으로 대신 사용할수 있는 것



함수가 요구하는 Delegate타입대신에 간단한 것이라서 한줄로 Lambda Expression으로 표현한 것이다
다음 페이지에서 Lambda 대신에 정식으로 Delegate를 사용해 보면 되겠다

비동기 버튼을 반복하여 실행크릭하시면
새로 Thread가 또 만들어지고, 또만들어진다
이전Thread는 끝날때까지 반복하고..
잘 관찰해 보시도록 버튼을 실행후 비활성화하여 다시 크릭하게 하지 않았다

***[LOG-IN]***

다음 화일에서 Invoke 매개변수를 Lambda expression으로 한 것과
Delegate 개체를 만들어서 사용하는 것을 비교하면서
VBA에서는 경험하지 못한 새롭고,중요한 개념을 챙겨 나가보자