变量backgroundWorker参数总是一样的吗?

时间:2012-09-24 14:40:37

标签: c# backgroundworker

我有以下代码:

// 1.
        public void RunSQL(QuerySetup querySetup)
        {
            //querySetup.Users is 10
            for (int i = 1; i <= querySetup.Users; i++)
            {
                querySetup.CurrentUser = i;
                var worker = new BackgroundWorker {WorkerReportsProgress = true};
                worker.DoWork += worker_DoWork;
                worker.RunWorkerCompleted += worker_RunWorkerCompleted;
                worker.RunWorkerAsync(querySetup);
            }
        }


    // 2.
    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        var querySetup = e.Argument as QuerySetup;
        // Doing stuff...
        e.Result = querySetup.CurrentUser;
    }

    // 3.
    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("User " + e.Result.ToString() + " is done.");
    }

我的目标是,最终我得到:

用户1已完成

用户2完成

...

用户10完成

(不按特定顺序)

但我只获得10倍“用户10已完成”。

但为什么呢?我需要以某种方式标记我的工作进程,以便我以后可以识别它。

3 个答案:

答案 0 :(得分:4)

是的,这里只有1个querySetup对象,主循环将不断更改currentUser 所有线程都将共享该单个对象。

 for (int i = 1; i <= querySetup.Users; i++)
 {
     querySetup.CurrentUser = i;
     ... 
     worker.RunWorkerAsync(querySetup);
 }

基本解决方案(如果您不需要其他querySetup成员)

 for (int i = 1; i <= querySetup.Users; i++)
 {
     //querySetup.CurrentUser = i;
     ... 
     worker.RunWorkerAsync(i);
 }

答案 1 :(得分:2)

QuerySetup只有一个实例。

您正在将此当前用户存储在此实例上。因此,当前用户将始终是循环中的最后一个用户。

答案 2 :(得分:1)

如果所有工作人员在循环结束后完成,那么他们都将看到querySetup.CurrentUser的全局状态,此时为10。

多线程的最佳方法是不共享线程之间的状态(因为这会强制您同步对该状态的访问),而是为每个线程函数提供自己的数据副本。在这种情况下,这意味着您不是提供querySetup作为线程函数的数据,而是提供querySetup.CurrentUser