【问题标题】:Explain to me this BackgroundWorker Event please请向我解释一下这个 BackgroundWorker 事件
【发布时间】:2013-01-18 21:25:24
【问题描述】:

我正在尝试使用 BackgroundWorker,并尝试根据事件通知我的主线程。这些东西对我来说都是新的,想问一下,我做得还好吗。

我用以下方式简化了我的一个winforms问题:(它只有1个按钮,当我按下它时在另一个线程中计数到十)

public partial class Form1 : Form
{
    public void Subscribe(CountToTen c)
    {
        c.HandleWorkerEvent += new CountToTen.WorkerHandler(OtherThreadFinished);
    }
    private void OtherThreadFinished(CountToTen c, EventArgs e)
    {
        Debug.WriteLine("I'm ready !!!");
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void btn_do_Click(object sender, EventArgs e)
    {
        CountToTen newThread = new CountToTen();
        Subscribe(newThread);
        newThread.StartCountingAndReportIfFinished();
    }
}

CountToTen 类:

public class CountToTen
{

    public event WorkerHandler HandleWorkerEvent;
    public EventArgs e;
    public delegate void WorkerHandler(CountToTen c, EventArgs e);
    public void StartCountingAndReportIfFinished()
    {
        BackgroundWorker worker = new BackgroundWorker();

        worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            for (int i = 1; i <= 10; i++)
            {
                Thread.Sleep(300);
                Debug.WriteLine("Counting :" + i.ToString());

            }
        };

        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs args)
            {
                Debug.WriteLine("Fromt Thread2 : I am finished!");
                if (HandleWorkerEvent != null)
                {
                    HandleWorkerEvent(this, e);
                }
            });

        worker.RunWorkerAsync();
        worker.Dispose();
    }
}

我试图在 BW 完成后创建一个事件,并在我的主窗体中订阅此事件。 它工作正常,但是,我真的不明白这一行发生了什么:

worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs args)
            {
                Debug.WriteLine("Fromt Thread2 : I am finished!");
                if (HandleWorkerEvent != null)
                {
                    HandleWorkerEvent(this, e);
                }
            });

我不是在这里为我的 BW 创建一个事件,当它完成后,然后为主线程调用另一个事件?这不是矫枉过正吗?我也可以直接订阅 RunWorkerCompleteEventHandler 吗?

这里有点迷糊,请初学者指教。 谢谢

【问题讨论】:

  • worker.RunWorkerAsync 之后立即调用worker.Dispose()哎哟!将此移动到RunWorkerCompleted 事件中!
  • 好的,感谢您的信息,不知道这一点,并按照您所说的移动。但它似乎仍然可以正常工作......

标签: c# winforms


【解决方案1】:

这是对 BackgroundWorker 的 RunWorkerCompleted 事件的订阅。您可以使用匿名方法或命名方法来执行此操作。您也可以通过这种方式删除委托类型声明:

worker.RunWorkerCompleted += (o, args) => 
{
    // raise HandleWorkerEvent if there is any subscriber exists
    if (HandleWorkerEvent != null)    
        HandleWorkerEvent(this, e);

    worker.Dispose();
};

使用命名方法,这看起来像

worker.RunWorkerCompleted += Worker_RunWorkerCompleted;

处理程序:

void Worker_RunWorkerCompleted(object o, RunWorkerCompletedEventArgs args)
{
    if (HandleWorkerEvent != null)    
        HandleWorkerEvent(this, e);

    ((BackgroundWorker)o).Dispose();
}

顺便说一句,我认为最好有类,它只会数到十个逻辑。在表单上创建 BackgroundWorker,并在 DoWork 事件处理程序中使用此类。表单也会处理它的所有组件。

【讨论】:

  • 所以可以肯定的是,您是说通过这一行我订阅了 BW Completed Event? ( worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs args) ) 我猜这些代表把我搞糊涂了——VS 在你的第一个 sn-p 上也有一些语法问题,但到目前为止谢谢!
  • @Onsightfree Lambda expressions 自 VS 2008 起可用。你有哪个 VS?
  • 我有2012express,但我想通了,它必须是};并不是 });。只是一个括号太多了,仅此而已:)
  • @Onsightfree 抱歉,您的原始代表创建中留下的括号 :) 现在已删除。再次,考虑在您的表单上使用 BW。放置到表单时,BW 注册为组件,因此当表单关闭时,BW 会自动释放。
  • 谢谢,我会试一试,但它又给我带来了很多问题,因为下一步我想报告进度,而且我已经知道如何在这个架构中(将稍后将其用于 FTP)。如果我无法弄清楚,将发布另一个关于此的问题:)
【解决方案2】:
Am I not creating an event here for my BW, when it is finished,
 and then call the another for the main thread?

是的。您正在处理 CountToTen 类中的 BackgroundWorker 事件。显然,根据您的类架构,通过事件通知您的主窗体的唯一方法。

  Is it not overkill? Could I subscribe directly to the RunWorkerCompleteEventHandler
  as well? 

当然可以..您的 BackgroundWorker 不会直接暴露给主窗体,否则您可以从那里订阅 RunWorkerCompletedEvent。

注意: 您不必调用 Dispose()。 它通过 Component 实现 IDisposable 接口。 详情see here

更新

  • 另一种方式

    public partial class Form1 : Form
    {
      private void btn_do_Click(object sender, EventArgs e)
      { 
        CountToTen obj= new CountToTen();
         obj.bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
         obj.bw.RunWorkerAsync();
       }
    
       void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){}       
    }
    class CountToTen 
    {
    public BackgroundWorker bw = new BackgroundWorker();
    public CountToTen()
    {
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    }
    
    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        //Do your Stuff
    }
    }
    

【讨论】:

  • 我刚刚意识到我的问题也不够清楚,这就是为什么我不确定我是否理解你答案的第二部分。您是说在我上面发布的代码中,我无法从我的主窗体订阅 BW 事件,因为它是在另一个类的方法中创建的?
  • 完全正确..您是否尝试通过在方法外部创建后台工作人员并将其公开给主窗体来从主窗体访问后台工作人员的事件
  • 谢谢,我接受了您的方法作为答案,因为它对我来说更清晰,因为它是 lazyberezovsky 的。可惜我不能同时接受。干杯
【解决方案3】:

您可以直接订阅 BackgroundWorker 的 RunWorkerCompleted 事件,但这取决于您的业务逻辑和架构。

【讨论】:

    猜你喜欢
    • 2014-03-24
    • 2013-03-31
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    • 2013-11-19
    • 2014-04-04
    相关资源
    最近更新 更多