2009-02-06 5 views
0

웹 사이트를 긁어 모으기 위해 내 응용 프로그램에서 스레딩을 구현했습니다. 모든 사이트가 스크랩 된 후 처리해야합니다.GUI로 진행하는 스레드

양식은 queueworker (2 명의 작업자를 생성하고 작업을 처리)를 만듭니다. 모든 작업이 끝나면 formack에서 baack을 처리하려고합니다.

public event EventHandler<ProgressEvent> UrlScanned; 

if (UrlScanned != null) 
{ 
     UrlScanned(this, new ProgressEvent(task.Name, 1)); 
} 

와 함께 해당 이벤트를 잡을 :

urlscanner.UrlScanned += new EventHandler<ProgressEvent>(UrlScanningProgress);  

private void UrlScanningProgress(object sender, ProgressEvent args) 
{ 
    if (pbarurlScan.InvokeRequired) 
    { 
     //don't use invoke when Thread.Join() is used! Deadlock 
     Invoke(new MethodInvoker(delegate() { UrlScanningProgress(sender, args); 
     //BeginInvoke(new MethodInvoker(delegate() { UrlScanningProgress(sender, args)}; 
    } 
    else 
    { 
       pbarurlScan.Value++; 
    } 
} 

문제는 작업이 내가 (queueworker에서) 발사 미리 형성 한 후이 시점에서 나는

public void WaitForCompletion() 
    { 
     // Enqueue one null task per worker to make each exit. 
     StopWorkers(); 

     //wait for the workers to finish 
     foreach (Thread worker in workers) 
     { 
      worker.Join(); 
     } 
    } 

으로이 accieved formthread가 막히고 Invoke를 호출하면 전체 애플리케이션이 교착 상태에 처하게됩니다.

어떻게 교착 상태를하지 않고 formthread에 대한 업데이 트를주고

답변

2

왜 당신이 가입하고있는 (노동자 스레드가 완료되면 begininvoke 발생)을 immidiate 업데이트가 할 수 있습니까? 각 스레드의 끝에서 콜백을 발생시킵니다. 아마도 카운터를 감소시킬 것입니다. 카운터가 0, 이되면을 UI 스레드로 콜백하고 "완료되었습니다"코드를 수행합니다. 다음과 같습니다.

using System.Windows.Forms; 
using System.Threading; 
using System; 
class MyForm : Form 
{ 

    public MyForm() 
    { 
     Button btn = new Button(); 
     Controls.Add(btn); 
     btn.Text = "Go"; 
     btn.Click += btn_Click; 
    } 
    int counter; 
    void btn_Click(object sender, System.EventArgs e) 
    { 
     for (int i = 0; i < 5; i++) 
     { 
      Interlocked.Increment(ref counter); 
      ThreadPool.QueueUserWorkItem(DoWork, i); 
     } 
    } 
    void DoWork(object state) 
    { 
     for (int i = 0; i < 10; i++) 
     { // send progress 
      BeginInvoke((Action)delegate { Text += state.ToString(); }); 
      Thread.Sleep(500); 
     } 
     EndThread(); // this thread done 
    } 
    void EndThread() 
    { 
     if (Interlocked.Decrement(ref counter) == 0) 
     { 
      AllDone(); 
     } 
    } 
    void AllDone() 
    { 
     Invoke((Action)delegate { this.Text += " all done!"; }); 
    } 
    [STAThread] 
    static void Main() 
    { 
     Application.Run(new MyForm()); 
    } 
} 
+0

'쉬운 일'을 위해 모든 것을 수행하기 위해 조인을 사용했습니다. 그래서 양식에 UrlScanningComplete 처리기를 만듭니다. 그리고 모든 작업이 완료되면 queueworker에서 이벤트가 발생합니까? – RvdK

+0

그런 접근법은 괜찮지 만 폼에서 실제 작업을하기 전에 어느 시점에서 UI 스레드 (Invoke/BeginInvoke)로 전환해야합니다. –

0

모든 작업이 완료되면 이제 별도의 이벤트가 발생합니다. AllUrlsScanned 이벤트를 수신 할 때 호출 될 별도의 함수로 작업을 처리하기위한 논리를 이동했습니다.

관련 문제