簡體   English   中英

當RunWorkerAsync被調用一次時,BackgroundWorker的DoWork被調用兩次?

[英]DoWork of BackgroundWorker is called twice when RunWorkerAsync is called once?

我已經在一個可以工作的類中創建了一個backgroundworker,但是如果我調用並等到結束運行,則第二次調用它,它將執行相同的過程兩次

我認為bw.DoWork什么問題+ =

private void button1_Click(object sender, EventArgs e)
{
    nptest.test.start("null", "null");    
}


namespace nptest
{
    class test
    {
        public static void start(string str, string strb)
        {
            if (bw.IsBusy != true)
            {
                bw.WorkerSupportsCancellation = true;
                bw.DoWork += (obj, e) => bw_DoWork(str, strb);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                bw.RunWorkerAsync();
            }
        }
        private static BackgroundWorker bw = new BackgroundWorker();
        private static void bw_DoWork(string str, string strb)
        {
            System.Windows.Forms.MessageBox.Show("initializing BackgroundWorker");
        }
        private static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                Console.WriteLine("Canceled");
            }
            else if (!(e.Error == null))
            {
                Console.WriteLine("Error: " + e.Error.Message);
            }
            bw.Dispose();

        }
    }
}

問題解決了

  class test
    {
        private static List<object> arguments = new List<object>();

        // initializing with program startup
        public static void bwinitializing()
        {
            bw.WorkerSupportsCancellation = true;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        }

        public static void start(string str, string strb)
        {
            if (bw.IsBusy != true)
            {
                arguments.Clear();
                arguments.Add(str);
                arguments.Add(strb);
                bw.RunWorkerAsync(arguments);
            }
        }
        private static BackgroundWorker bw = new BackgroundWorker();
        private static void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            List<object> genericlist = e.Argument as List<object>;
            System.Windows.Forms.MessageBox.Show("BackgroundWorker " + genericlist[0]);

        }

我懷疑會不小心添加了多個 DoWork事件。

也就是說, 每次調用start方法時,它都會注冊一個新的 DoWork事件處理程序。 將添加不是替換現有的處理程序DoWork處理程序。 因此,將有多個DoWork處理程序被稱為后續時間DoWork等。

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

我建議不要在這里使用閉包,而應該使用方法組(將其隱式轉換為委托),然后將數據傳遞給RunWorkerAsync調用(有一種接受數據參數的形式)。

RunWorkerCompleted +=行沒有此問題,因為它從方法組傳遞了一個委托(保證始終評估為同一委托對象1 )。 因此,對該行重復的+=調用替換處理程序。


例:

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我不確定是否可以保證等於引用相等,但是即使使用new DelegateType(MethodGroup)獲得,使用此方法也可以從方法組的委托中穩定調用+=-=

Wrt。 我在主的評論:如果UI元素是從上他們沒有創建的線程訪問的話,會有好玩的“跨線程操作異常”。 我相信對消息框的這種使用是“可以的”(當不是使用所有者從另一個線程創建時),但是在BackgroundWorker的DoWork中訪問UI的做法通常是可疑的。


另外, 不要在這里調用bw.Dispose() 用擁有的容器或上下文處置它。 這似乎是很好的和良性的在這種情況下,但只做到這一點時BGW實例將永遠不會再使用。 從事件處理程序中調用它也是可疑的,因為BGW仍處於“活動”狀態。

我遇到了與以上評論員“ Power-Mosfet”相同的問題

最后,添加一個new BackgroundWorker()然后分配給全局bw值將解決我的問題。

代碼是,從:

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

至:

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);

}

還有另一個原因。 在其生成的代碼中查找DoWorkEventHandler InitializeComponent()如果您是通過組件UI屬性生成的,並且還需要自己注冊。

因為如果再次注冊它,它將不會覆蓋前一個,但是會添加另一個事件,並且將調用兩次。

在我的情況下,BackgroundWorker運行了兩次,因為在我的窗體的構造函數類中,我聲明了DoWork,ProgressChanged和RunWorkerCompleted事件處理程序,但Visual Studio 2013已在此窗體類的Designer部分中聲明了它。

因此,我只是刪除了聲明,但效果很好。

謝謝...。這段代碼運行良好。為backroundworker創建新實例是個好主意。...現在,我們可以在for / while循環中調用此函數,並可以運行多個backgroundworker進程。

單擊按鈕后,我進行了這樣的編碼..而不影響主線程的流...多個進程將在背面運行....我只是使用消息框彈出了..但是我們可以做一些耗時的過程來在“ bgwDownload_DoWork“函數...,將創建多個進程...,而我們不需要檢查BackgroundWorker是否忙...

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
}

我今天遇到了這個問題,當我注意到每次顯示表單時,都會多次調用后台工作程序RunWorkerCompleted事件,因此我將后台工作程序置於正在執行長時間運行任務的彈出窗體上。

我的問題是關閉表單后我沒有處理該表單,這意味着每次我顯示該表單時,都會在偶數中添加另一個處理程序。

處理完表格后解決了我的問題。 我想在我的情況下尋找解決方案時,只是想在這里提到它。

我從設計器中刪除了控件,並在代碼中實例化了一個新的WorkerProcess:

例如:var bwProcess = new BackgroundWorker();

bwProcess.DoWork + =新的DoWorkEventHandler(bwProcess_DoWork);

bwProcess.RunWorkerCompleted + = bwProcess_RunWorkerCompleted;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM