2009-11-30 8 views
0

스레딩, 델리게이트 및 배경 작업자로 약간의 게임을하기 위해 몇 가지 작은 응용 프로그램을 만들었습니다. 그 중 하나에 약간 문제가 있습니다. 텍스트 상자, 단추 및 richttext가있는 Windows 양식이 있습니다. 내가 버튼을 누르면 , 텍스트 상자의 텍스트는 다음과 같이 클래스를 인스턴스화 할 수 있었던 파라미터로 사용된다 :C# 스레딩 문제

public partial class Form1 : Form 
{ 
    private BackgroundWorker backgroundWorker; 

    public Form1() 
    { 
     InitializeComponent();    
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     backgroundWorker = new BackgroundWorker(); 
     backgroundWorker.DoWork += new DoWorkEventHandler(worker_DoWork); 
     backgroundWorker.RunWorkerAsync(); 
    } 

    void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     new Thread((ThreadStart)delegate() 
     { 
      this.BeginInvoke((ThreadStart)delegate() 
      { 
       foreach (string line in textBox1.Lines) 
       { 
        Dig digger = new Dig(line, textBox1.Text); 
        digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker); 

        string response = digger.GetAllInfo(); 

        richTextBox1.AppendText(response); 
        Application.DoEvents(); 
       } 
      }); 
     }).Start(); 
    } 

    void OnUpdateTicker(string msg) 
    { 
     new Thread((ThreadStart)delegate() 
     { 
      this.BeginInvoke((ThreadStart)delegate() 
      { 
       label4.Text = msg; 
       Application.DoEvents(); 
      }); 
     }).Start();    
    } 
} 

나는 'textBox1.Lines'로 실행 디버깅 할 때 유형의 예외가 발생했습니다 ' Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException ' 이 문제를 해결하는 방법에 대한 팁?

답변

5

먼저, DoWork 안에 새 스레드를 만들 필요가 없습니다. BackgroundWorker의 전체 아이디어는 DoWork이 별도의 스레드에서 실행된다는 것입니다. 둘째, DoWork은 별도의 스레드에서 실행되고 UI 컨트롤은 UI 스레드에서만 수정할 수 있으므로 이러한 업데이트를 올바르게 호출해야합니다. 그래서, worker_DoWork의 재 버전은 다음과 같이 수 : 코드가 명시 적으로에 실행을 강제하는 Control.Invoke 호출을 통해 또한 AppendText 메서드 호출이 수행하는 방법 새로운 스레드를 생성하고,하지 않는 방법

void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    foreach (string line in textBox1.Lines) 
    { 
     Dig digger = new Dig(line, textBox1.Text); 
     digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker); 
     string response = digger.GetAllInfo(); 
     richTextBox1.Invoke((Action) delegate { richTextBox1.AppendText(response); }); 
    } 
} 

주 UI 스레드

0

주된 이유는 텍스트 상자가 백그라운드 스레드 소유가 아니라는 것입니다.

귀하의 UI 스레드는 모든 UI 개체를 소유하고 있으며 단추를 누를 때 배경 스레드를 위로 돌리고 있습니다. 이 백그라운드 스레드는 모든 UI 객체에 액세스해서는 안됩니다.

텍스트 상자의 값을 사용하려면 배경 스레드에 다른 값을 전달해야합니다.

Have a look here for an explanation (and solution).

0

당신이 명시 적으로 컨트롤의 .Invoke 방법을 사용하여 수행 괜찮은지 프로그램을 이야기하지 않는 한 당신은 주 스레드 자체에서 주 스레드에서 컨트롤을 업데이트 할 수 있습니다. 다중 스레드 윈도우에서 Control.Invoke

From: http://www.albahari.com/threading/part3.aspx 

는 그것을 만든 하나가 아닌 다른 스레드에서 컨트롤 메서드 또는 속성을 호출하는 불법 Forms 응용 프로그램. 모든 크로스 스레드 호출은 Control.Invoke 또는 Control.BeginInvoke 메서드를 사용하여 컨트롤 (일반적으로 주 스레드)을 만든 스레드에 명시 적으로 마샬링되어야합니다. 너무 늦게 발생하기 때문에 자동화 된 마샬링에 의존 할 수 없습니다. 실행이 비 관리 코드에 잘 들어갈 때만, 내부 .NET 코드가 이미 스레드 안전하지 않은 "잘못된"스레드 코드에서 실행되었을 수 있습니다.