我有以下代码:
// 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已完成”。
但为什么呢?我需要以某种方式标记我的工作进程,以便我以后可以识别它。
答案 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