IT/C#

[C#] 크로스쓰레드

데브렉스 2011. 1. 11. 07:43
반응형

[질문]

"한 스레드에 만든 컨트롤은 다른 스레드에 있는 컨트롤의 부모가 될 수 없습니다."

 라는 오류가 발생합니다.

- Form class

- ClassA (내부에서 Thread 생성)

- ClassB (내부에 DataTable 개체 소유)

 

Form은 ClassA를 멤버로 가지며, ClassA는 ClassB를 멤버로 가집니다.

A에서 생성된 Thread에서 ClassB에 Form의 DataGrid 참조를 넘기면 ClassB는 참조를 받아 이 그리드의 DataSource를 설정하는 부분에서

위와 같은 오류가 발생합니다.

 조언 부탁드립니다... ^^

 좋은 하루 되세요~


 ----------------------------------------------------------------------------------------

 [답변]

 
 Thread와 Windows 컨트롤간에 관계가 복잡합니다.

 그것은 window에 GDI를 담당하는 스레드와 실제 작업을 하는 워크 스레드 그리고 사용자가만든 스레드 간의

 이해 관계입니다. 이걸 설명하려면 ㅡㅡㅋ 찾아봐야하겠지만

 이해하기도 어렵습니다.

 스레드로 작업한 값을 컨트롤에 적용하기 위한 부분을 Control.Invoke()를 사용하도록 지원하고 있습니다.

---------------------------------------------------------------------------------------
InvalidOperationException 이 맞는지요???

내용을 보니..맞는거 같은데 말이죠..

아니면 패스..하세요..ㅋ

하나의 스레드에서 만든 컨트롤에 대한 엑세스는 그 스레드 영역에서만 가능 합니다.

하지만 스레드 프로그램상에서 이 원칙을 지킬려면..ㅋ

방법은 간단해요..

델리게이트를 쓰는거에요.

 메인 스레드에서 델리게이트로 델리게이트메소드를 만들어 인보크 해서 그 메소드에서 컨트롤에 대한 핸들링을 하시면 됩니다.

  아래 코드는 메인 폼 페이지에 있구요

  fileHandling 는 님의A 클래스에 해당 됩니다.

B클래스의 이벤트를 A클래스에 넘기고 A클래스의 이벤트를 메인폼에 넘긴 코드입니다.

아래 코드에서..

SetRowCount() 내용을 델리게이트로 호출하지 않고 바로 사용하게 되면..

Cross Thread 즉..InvaildOperationException 예외가 발생하게 됩니다...

 ---------------------------------------------------------------------

       private delegate void CallbackRowCount(int count);

 

 

        private void fileHandling_OnRowCount(object sender, RowCountEventArgs e)

        {

            if (this.progressBar1.InvokeRequired)

            {

                CallbackRowCount c = new CallbackRowCount(SetRowCount);

                this.Invoke(c, e.TotalCount);

            }

        }

 

        private void SetRowCount(int count)

        {

            this.progressBar1.Maximum = count;

            this.progressBar1.PerformStep();

            Application.DoEvents();

        }
 
 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 비주얼스튜디오 2005로 작업 하고 있습니다.   닷넷프레임웍 2.0

1.1에서는 잘 돌아가는 코드 입니다.

다음과 같이 했는데 크로스 쓰레드 라는 에러가 발생 합니다.

thread th;   // 전역 변수로 선언

A() 메소드

try {

    while ( true ) {

      작업

        .

        .

        .

    }

}  catch {

        레이블컨트롤.Text = "에러";

}

 

 

버튼 클릭 이벤트()

 

this.th = new Thread ( new ThreadStart ( A ) );

th.Start();

 

 

 

 

 

간단하게 이런 코드 인데

레이블컨트롤.Text = "에러";     <= 이 부분에서

자기가 생성하지 않은  쓰레드에 접근 ?     [ 에러내용이 자세하게 생각나지 않네요..]

대략 이런 메세지를 보내면서   크로스쓰레드 에러를 발생합니다.

하지만  레이블컨트롤.Text = "에러"; 이부분을 주석처리 하면 에러가 나지 않습니다.

저 레이블콘트롤은  SplitContainer컨트롤의 Panel1에  있습니다.

무슨 에러이며, 해결 방법  부탁드립니다.
 
 ---------------------------------------------------------------------------------------

컨트롤을 만든 쓰레드만 컨트롤을 다룰 수 있습니다.

다른 쓰레드에서는 간접적인 방법으로 컨트롤을 만든 쓰레드에게 요청을 할 수 있습니다.

             this.Invoke(new MethodInvoker(delegate()

            {

                this.label1.Text = "Test";

            }));

 

원래 MethodInvoker의 인수는 메소드여야 하는데 .NET 2.0 부터는

[출처] 크로스 쓰레드|작성자 whwh0207

반응형

'IT > C#' 카테고리의 다른 글

[C#] C#과 MSSQL2005 연동하기 개돌 - 1편  (0) 2011.01.11
[C#] Effective c# 책 정리 요약  (0) 2011.01.11
[C#] c#을 이용한 usb 연결, 연결해제 처리  (0) 2011.01.11
[C#] PC 종료 코드  (0) 2011.01.11
[C#] 메모리 Leak?  (0) 2011.01.11