2009-02-06 23 views
0

我在我的应用程序中实现了线程抓取网站。在所有的网站报废后,我想处理它们。线程进度到GUI

表单创建队列工(创建2个工作者并处理任务)。 完成所有任务后,我想要在formthread中处理它们。 在这一点上我与

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这个任务被预制后,我火了(从queueworker):

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++; 
    } 
} 

的问题是formthread被阻塞,并调用Invoke,现在整个应用程序处于死锁状态。

如何,我可以给更新到formthread无需死锁,并有immidiate更新(如果的BeginInvoke工人线程完成时)

回答

2

你为什么这样做的加入?我会在每个线程结束时提出一个回调 - 可能会减少一个计数器。当计数器变为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

我用这个连接'easy'等待一切都完成了。 因此,在窗体中创建一个UrlScanningComplete处理程序。如果所有的任务都完成了,那么从排队工发出一个事件? – RvdK 2009-02-06 12:43:30

0

当所有任务完成后,我立即启动一个单独的事件。我将用于处理任务的逻辑移至一个将在接收AllUrlsScanned事件时调用的独立函数。