DoWork of BackgroundWorker is called twice when RunWorkerAsync is called once?

前端 未结 7 1272
情深已故
情深已故 2020-12-06 01:51

I have create a backgroundworker in an class it works, but if i call and wait until the end run, call it for the second time it will do the same process twice

i thin

相关标签:
7条回答
  • 2020-12-06 01:54

    thank you....this code is working fine... creating new intance for backroundworker is good idea.... Now we can call this function in for/while loop and can run multiple backgroundworker process.

    I coded like this when button click is done.. without distrubting the main thread flow... multiple process will be running back side.... i just used messagebox to pop up..but we can do timetaking process to run in "bgwDownload_DoWork" function... and multiple process will be created... and her we need not check the BackgroundWorker is busy or not...

    private void button1_Click(object sender, EventArgs e)
    {
       for (int i = 0; i < 3; i++)
         yourFunction_bw(i);
    
     }
    private BackgroundWorker gBgwDownload;
    
    private void yourFunction_bw(int i)
    {
        // Create a background thread
        gBgwDownload = new BackgroundWorker(); // added this line will fix problem 
        gBgwDownload.DoWork += bgwDownload_DoWork;
        gBgwDownload.RunWorkerAsync(i);
    
    }
    
    private void bgwDownload_DoWork(object sender, DoWorkEventArgs e)
    {
      int stre = (int)e.Argument;
      MessageBox.Show(stre.ToString ()); // time taken process can be added here
    }
    
    0 讨论(0)
  • 2020-12-06 02:00

    I ran into this problem today, I put a background worker on a popup form that was doing a long running task when I noticed that every time I showed the form the background worker RunWorkerCompleted event was being called multiple times.

    My problem was that I was not disposing of the form after closing it, which meant every time I showed the form it added another handler to the even each time.

    Disposing of the form when finished with it solved my problem. Just wanted to mention it here as I came across this page when I went looking for a solution for my situation.

    0 讨论(0)
  • 2020-12-06 02:01

    I would suspect that multiple DoWork events are being inadvertently added.

    That is, every time the start method is called it registers a new DoWork event handler. This adds and does not replace the existing handler DoWork handler. So then there will be multiple DoWork handlers called subsequent times .. 1, 2, 3, etc.

    // creates a NEW delegate and adds a NEW handler
    bw.DoWork += (obj, e) => bw_DoWork(str, strb);
    

    I would recommend not using a closure here, but rather just use a Method Group (with implicit conversion to a delegate) and then pass the data to the RunWorkerAsync call (there is a form that takes an argument for data).

    The RunWorkerCompleted += line doesn't have this issue because it is passed a delegate from a Method Group (which is guaranteed to always evaluate to the same delegate object1). Thus the repeated += calls for that line will replace the handler.


    Example:

    class MyData {
       public string StrA { get; set; }
    }
    
    // These only need to be setup once (and should be for clarity).
    // However it will be "ok" now if they are called multiple times
    // as, since the delegates are the same, the += will
    // act as a replacement (as it replaces the previous delegate with itself).
    bw.WorkerSupportsCancellation = true;
    bw.DoWork += bw_DoWork;
    bw.RunWorkerCompleted += bw_RunWorkerCompleted;
    
    // Pass data via argument
    bw.RunWorkerAsync(new MyData {
        StrA = str,
    });
    
    void bw_DoWork (object sender, DoWorkEventArgs e) {
        var data = (MyData)e.Argument;
        var str = data.StrA;
        // stuff
    }
    

    1 I am not sure if it is guaranteed to be reference-equals equality, but using this approach allows for stable invoking of += and -= from the delegate from the Method Group even if obtained by new DelegateType(MethodGroup).

    Wrt. my comment in the main post: if UI elements are accessed from a thread on which they were not created then there will fun "Cross-thread operation exceptions". I believe this usage of a Message Box is "okay" (when not created with an owner from another thread), but the practice of accessing the UI in a BackgroundWorker's DoWork is generally dubious.


    Also, do not call bw.Dispose() here; dispose it with the owning container or context. It appears to be nice and benign in this case, but only do it when that BGW instance will never be used again. Calling it from an event handler is also dubious as the BGW is still "active".

    0 讨论(0)
  • 2020-12-06 02:01

    I removed the control from the designer and instantiate a new WorkerProcess in Code:

    example: var bwProcess = new BackgroundWorker();

    bwProcess.DoWork += new DoWorkEventHandler(bwProcess_DoWork);

    bwProcess.RunWorkerCompleted += bwProcess_RunWorkerCompleted;

    0 讨论(0)
  • 2020-12-06 02:15

    There is also another reason. look for DoWorkEventHandler in its generated code InitializeComponent() If you have generated it through compnent UI properties and also registering it yourself.

    Because if you register it again it will not override the previous one but will add another event and will call twice.

    0 讨论(0)
  • 2020-12-06 02:16

    I have encounter same problem as above commenter "Power-Mosfet"

    and in the end, added a new BackgroundWorker() then assigned to the global bw value will fix my problem.

    code is, change from:

    private BackgroundWorker gBgwDownload;
    
    private void yourFunction_bw(xxx)
    {
        // Create a background thread
        gBgwDownload.DoWork += bgwDownload_DoWork;
        gBgwDownload.RunWorkerCompleted += bgwDownload_RunWorkerCompleted;
        //omited some code
        gBgwDownload.RunWorkerAsync(paraObj);
    }
    

    to:

    private BackgroundWorker gBgwDownload;
    
    private void yourFunction_bw(xxx)
    {
        // Create a background thread
        gBgwDownload = new BackgroundWorker(); /* added this line will fix problem */
        gBgwDownload.DoWork += bgwDownload_DoWork;
        gBgwDownload.RunWorkerCompleted += bgwDownload_RunWorkerCompleted;
        //omited some code
        gBgwDownload.RunWorkerAsync(paraObj);
    
    }
    
    0 讨论(0)
提交回复
热议问题