글쓴이 보관물: Toughman

BackgroundWorker 클래스 사용

WinForm을 이용한 프로그램을 작업할 때 종종 오랜시간 반복적인 작업을 처리하여야 하는 경우가 있습니다. 진행되는 상태를 표시해 주고 일시 중지 혹은 작업이 마무리 되었을 때 사용자에게 알림 메시지를 보여주는 형식으로 작업을 하게 됩니다. 여기서 문제가 반복문안에 UI 를 갱신하는 코드를 넣으면 의도한 대로 동작하지 않게 됩니다. 특히 버튼 이벤트는 반응을 하지 않게되고 작업이 끝난 후 버튼이 눌려지는 듯한 현상을 보이게 됩니다. 이럴 때 BackgroundWorker 클래스 를 사용하여 작업하면 의도한 대로 버튼 이벤트가 발생되도록 할 수 있습니다. 이 클래스는 .Net 2.0 부터 추가되었고 자세한 설명은 다음의 링크에서 확인할 수 있습니다.

MSDN 설명 보기

사용자가 설정한 키워드 목록을 OpenAPI 를 이용하여 검색 결과를 가져오는 간단한 예제를 구성해 보겠습니다. 먼저 Form 을 아래와 같이 디자인 합니다. 처리되는 키워드와 진행 상황을 표시해 줄 Text, Label 컨트롤을 추가합니다.

폼 디자인

폼 디자인

BackgroundWorker 클래스 변수를 선언합니다. 그리고 폼이 초기화될 때 BackgroundWorker 클래스가 동작할 사항을 정의해 줍니다.

private BackgroundWorker bwWrite;

bwWrite = new BackgroundWorker();
bwWrite.WorkerSupportsCancellation = true;
bwWrite.DoWork += new DoWorkEventHandler(doWrite);
bwWrite.RunWorkerCompleted += new RunWorkerCompletedEventHandler(write_RunWorkerCompleted);

5번째 행에 doWrite 라는 메소드를 실행하도록 설정하고 6번째 행에 작업이 종료되면 write_RunWorkerCompleted 메소드가 실행되도록 설정하였습니다. doWrite 메소드에서는 시간이 오래 걸리는 루프 등의 루틴을 추가하면 됩니다. OpenAPI 를 통하여 검색결과를 가져오는 부분이 될 것입니다. write_RunWorkerCompleted 메소드에서는 doWrite 메소드의 호출이 완료되었을 때 원하는 동작을 하도록 작업하면 됩니다.

각 버튼 이벤트를 다음과 같이 정의합니다.

private void btnStart_Click(object sender, EventArgs e)
{
	btnStart.Enabled = false;
	btnStop.Enabled = true;

	bwWrite.RunWorkerAsync();
}

private void btnStop_Click(object sender, EventArgs e)
{
	bwWrite.CancelAsync();
	btnStart.Enabled = true;
	btnStop.Enabled = false;
}

6번째 행에서 이전에 정의한 대로 doWrite 메소드를 실행하도록 RunWorkerAsync 메소드를 호출합니다. 중지 버튼을 클릭하면 CancelAsync 메소드를 호출하여 취소되도록 합니다. 여기서 유의해야 할 것은 CancelAsync 메소드가 호출되었다고 해서 바로 종료되는 것이 아니라는 것 입니다. doWrite메소드 내에서 다음과 같은 방식으로  취소여부를 판단하여 종료하여야 합니다.

private void doWrite(object sender, DoWorkEventArgs e)
{
.
.
.
	for (var i = keywordIndex; i < keyword.Length; i++)
	{
		if (bwWrite.CancellationPending == true)
		{
			e.Cancel = true;
			return;
		}
		.
		.
		.
	}
}

작업진행 사항을 Text, Label의 속성을 변경시키는 방법으로 doWrite 메소드내에 코드를 작성하면 “자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다” 라는 오류가 발생합니다. 메시지 내용대로 별도의 스레드에서 폼에 생성된 컨트롤에 접근하려고 하여 발생되는 오류 입니다. 이럴때는 다음과 같이 Invoke 메소드를 호출하는 방식으로 처리합니다. 이렇게 하면 오류가 발생하지 않고 의도한 대로 진행상황을 Label 컨트롤에 나타낼 수 있습니다.

delegate void delegateSetProgressLabel(string text);

private void setProgressLabel(string text)
{
	if (lblProgressStatus.InvokeRequired)
	{
		var delegateCall = new delegateSetProgressLabel(setProgressLabel);

		this.Invoke(delegateCall, text);
	}
	else
	{
		lblProgressStatus.Text = text;
	}
}

간략하게  BackgroundWorker 클래스 사용 방법에 대하여 알아보았습니다.

이케아 레르함(LERHAMN) 테이블

작은 테이블이 필요하여 인터넷으로 알아보고 대형마트에도 방문하여 보았지만 마음에도 들지 않고 가격이 생각보다 비쌌습니다. 이전에 홈페이지에서 보아두었던 이케아 레르함(LERHAMN) 테이블 을 방문한 김에 실물을 살펴보고 마음에 들어 구매하게 되었습니다. 크기는 알고 있어던 터라 재질 및 실제 높이가 궁금했습니다. 상판이 조금 얇은 듯 한고 다리가 얇아 보이는데 필자는 아주 튼튼한 테이블은 필요없어서 큰 고민없이 선택하게 되었습니다.

이케아 레르함(LERHAMN) 테이블 상자 모습. 두개의 포장이 하나의 세트로 이루어져 있다.

이케아 레르함(LERHAMN) 테이블 상자 모습. 두개의 포장이 하나의 세트로 이루어져 있다.

제품이 있는 곳에 가보면 다른 것과는 달리 두개의 포장이 하나의 세트로 되어 있어 누락이 되지 않게 잘 챙겨서 가져가야 합니다. 설명이 잘 되어 있으니 빠뜨릴 염려는 거의 없습니다. 누락이 되면 계산대에서 체크가 되는지는 모르겠습니다.

상자에 인쇄된 설명

상자에 인쇄된 설명

작은 상자를 개봉한 모습

작은 상자를 개봉한 모습

작은 상자를 개봉해 보면 테이블 다리와 조립에 필요한 부속물이 들어 있습니다. 역시나 딱 맞게 들어있습니다.

조립에 필요한 부속물

조립에 필요한 부속물

조립자체는 어렵지 않습니다. 설명서를 보고 따라하면 쉽게 조립할 수 있습니다.

상판을 받치게 될 부분 조립

상판을 받치게 될 부분 조립

먼저 상판을 받치게 될 부분을 위의 이미지와 같이 4개 조립합니다. 그 다음 모두 연결하면 다음과 같은 모양이 됩니다.

4개를 모두 연결한 모습

4개를 모두 연결한 모습

그 다음으로 상판을 부착하면 되는데 작업의 특성상 바닥에 놓고 진행하여야 합니다. 여기서 주의할 점은 상판에 흠집이 나지 않도록 작업해야 한다는 것 입니다. 설명서에는 모포를 깔고 그 위에서 작업하라고 되어 있는데 필자는 깔만한 것이 없어서 포장 상자 위에 놓고 작업하였습니다.

위의 이미지에서 보는바와 같이 총 12개의 나사를 조여야 하는데 크기도 크고 개수도 많아 조금 힘이 듭니다. 전동 공구가 있으면 훨씬 수월하게 작업하실 수 있습니다. 필자는 그냥 손으로 했는데 몇개 하니까 손이 얼얼해서 쉬다가 작업했습니다.

상판을 붙인 모습

상판을 붙인 모습

그 다음으로는 다리를 붙여 완성하면 됩니다.

다리 부분에 나사를 넣은 모습

다리 부분에 나사를 넣은 모습

다리를 아래와 같은 모습으로 붙이고 와셔와 너트를 조여주면 조립이 완성됩니다.

다리를 붙인 모습

다리를 붙인 모습

와셔와 너트를 조인 모습

와셔와 너트를 조인 모습

제품의 정보와 가격은 다음 주소에서 확인하실 수 있습니다.

http://www.ikea.com/kr/ko/catalog/products/60264272/