C# 线程进程到GUI

C# 线程进程到GUI,c#,multithreading,user-interface,deadlock,C#,Multithreading,User Interface,Deadlock,我在我的应用程序中实现了用于抓取网站的线程。在所有的网站都被刮,我想处理他们 表单创建queueworker(它创建2个Worker并处理任务)。 所有任务完成后,我想在formthread中处理它们。 在这一点上,我明白了这一点 public void WaitForCompletion() { // Enqueue one null task per worker to make each exit. StopWorkers();

我在我的应用程序中实现了用于抓取网站的线程。在所有的网站都被刮,我想处理他们

表单创建queueworker(它创建2个Worker并处理任务)。 所有任务完成后,我想在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();
        }
    }
执行任务后,我将(从queueworker)激发:

公共事件事件处理程序URL扫描;
如果(URLScanted!=null)
{ 
URLScanted(这是新的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++;
   }
}
urlscanner.UrlScanned+=新事件处理程序(UrlScanningProgress);
私有void UrlScanningProgress(对象发送方,ProgressEvent参数)
{
if(pbarurlScan.invokererequired)
{
//使用Thread.Join()时不要使用invoke!死锁
Invoke(新的MethodInvoker(delegate(){UrlScanningProgress(sender,args));
//BeginInvoke(新方法调用程序(委托(){UrlScanningProgress(发送方,args)};
}
其他的
{
pbarurlScan.Value++;
}
}
问题是formthread被阻塞,通过调用Invoke,整个应用程序现在处于死锁状态


如何在没有死锁的情况下更新formthread并进行immidate更新(如果workers线程完成,则会发生begininvoke)

为什么要执行联接?我会在每个线程结束时发出回调,可能会减少计数器。当计数器变为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());
    }
}
使用System.Windows.Forms;
使用系统线程;
使用制度;
类MyForm:Form
{
公共MyForm()
{
按钮btn=新按钮();
控件。添加(btn);
btn.Text=“Go”;
点击+=btn\U点击;
}
整数计数器;
无效btn_单击(对象发送者,System.EventArgs e)
{
对于(int i=0;i<5;i++)
{
联锁增量(参考计数器);
QueueUserWorkItem(DoWork,i);
}
}
无效DoWork(对象状态)
{
对于(int i=0;i<10;i++)
{//发送进度
BeginInvoke((操作)委托{Text+=state.ToString();});
睡眠(500);
}
EndThread();//此线程已完成
}
void EndThread()
{
if(联锁减量(参考计数器)==0)
{
AllDone();
}
}
void AllDone()
{
调用((操作)委托{this.Text+=“全部完成!”;});
}
[状态线程]
静态void Main()
{
运行(新的MyForm());
}
}

现在,当所有任务都完成时,我会触发一个单独的事件。我将处理任务的逻辑移动到一个单独的函数,该函数将在接收AllurlsCanned事件时调用。

我使用连接“轻松”等待一切完成。因此,在表单中创建一个UrlScanningComplete处理程序。如果l任务完成了吗?这种方法很好,但是在对表单进行任何实际工作之前,您仍然需要在某个时候切换到UI线程(Invoke/BeginInvoke)。
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());
    }
}