C# 结果为';使用reportprogress时不正确
我有一个listview,其中有添加静态项和文本值序列:1,2,3,4,5,6 当我选择项目时,将执行相应的backgroundworker线程 e、 g:我选择了3个项目,让3个backgroundworker线程执行 在我将reportprogress of backgroundworker添加到dislay progressBar之前,一切都正常,所以当选择的项目不正确时,结果是正确的C# 结果为';使用reportprogress时不正确,c#,winforms,backgroundworker,C#,Winforms,Backgroundworker,我有一个listview,其中有添加静态项和文本值序列:1,2,3,4,5,6 当我选择项目时,将执行相应的backgroundworker线程 e、 g:我选择了3个项目,让3个backgroundworker线程执行 在我将reportprogress of backgroundworker添加到dislay progressBar之前,一切都正常,所以当选择的项目不正确时,结果是正确的 e、 g:我选择了3个项目,文本值为2,3,5,所以结果显示为2,2,5 我尝试调试,但找不到错误 谁来
e、 g:我选择了3个项目,文本值为2,3,5,所以结果显示为2,2,5 我尝试调试,但找不到错误 谁来帮帮我,求你了
private static int numOfTheards = 0;
BackgroundWorker[] threadArray;
List<string> lst = null;
int i ;
private void InitializeBackgoundWorkers()
{
for (int f = 0; f < numOfTheards; f++)
{
threadArray[f] = new BackgroundWorker();
threadArray[f].DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
threadArray[f].RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
threadArray[f].ProgressChanged +=new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
threadArray[f].WorkerReportsProgress = true;
threadArray[f].WorkerSupportsCancellation = true;
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string kq = "";
while (i < lst.Count)
{
kq = lst[i];
(sender as BackgroundWorker).ReportProgress(i * 100 / listViewEx1.Items.Count);
++i;
break;
}
labelX1.Invoke(new MethodInvoker(delegate { labelX1.Text += kq + "-"; }));
}
private void buttonX1_Click(object sender, EventArgs e)
{
i = 0;
labelX1.Text = "";
InitializeBackgoundWorkers();
for (int a = 0; a < numOfTheards; a++)
{
if (threadArray[a].IsBusy)
{
threadArray[a].CancelAsync();
}
else
{
progressBarX1.Value = progressBarX1.Minimum;
threadArray[a].RunWorkerAsync();
}
}
}
private void listViewEx1_SelectedIndexChanged(object sender, EventArgs e)
{
labelX2.Text = "";
numOfTheards = listViewEx1.SelectedItems.Count;
threadArray = new BackgroundWorker[numOfTheards];
lst = new List<string>();
foreach (ListViewItem item in listViewEx1.SelectedItems)
{
lst.Add(item.SubItems[0].Text);
labelX2.Text += item.SubItems[0].Text+".";
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBarX1.Value = e.ProgressPercentage;
progressBarX1.Text = "Processing......" + progressBarX1.Value.ToString() + "%";
}
private static int numOfTheards=0;
BackgroundWorker[]线程数组;
列表lst=null;
int i;
私有void初始化backgoundworkers()
{
for(int f=0;f
您在理解多线程时似乎遇到了严重问题。例如,您正在使用一个全局变量i
,该变量由后台工作代码修改-什么告诉您没有竞争条件?(很明显,这里有比赛条件,否则你就不会有现在的问题了
至少marki
volatile
,更好的是,真正重新思考您的代码设计
顺便说一句,问题的出现并不令人惊讶。我将解释原因: 您使用公共变量
i
来确保3名后台工作人员在列表中工作,但他们中没有两人在同一项上工作。在您的情况下,这显然不起作用,因为您没有实现任何正确的方法来确保只有一名后台工作人员单独处理一个条目
示例:两个后台工作人员开始工作。他们都获得要处理的值i==0
,因为您没有确保操作“在索引处获取项i
”和“增量i
”是原子的(意思是:被视为一个操作,没有其他线程可以干扰)
您可以做的是完全像这样锁定对i
的访问:
private volatile int i;
private object iLock = new object();
...
while (i < lst.Count)
{
int previousI;
lock (iLock)
{
previousI = i;
kq = lst[i];
++i;
}
(sender as BackgroundWorker).ReportProgress(previousI * 100 / listViewEx1.Items.Count);
...
}
此代码已经错误。您调用InitializeBackgroundWorkers
,它实际初始化数组中的新后台工作人员,该数组是在listViewEx1\u SelectedIndexChanged
中新创建的。取消此代码中的任何工作人员都没有用,因为它们无法运行,因为您只创建了它们。如果要取消运行工作人员,请在创建新的工作数组之前,您需要先取消它们,然后才能在列表视图ex1\u SelectedIndexChanged
中创建新的工作数组。但这只是一个旁注
初始化worker后,为每个worker生成要处理的数据。我知道您希望每个worker处理子项[0]
在列表视图中选择的一个项目。要处理的项目列表已在列表视图ex1\u SelectedIndexChanged
:lst
中生成。因此,由于现在lst
中的每个项目都有一个后台工作人员,这归结为:
private void buttonX1_Click(object sender, EventArgs e)
{
i = 0;
labelX1.Text = "";
InitializeBackgoundWorkers();
progressBarX1.Value = progressBarX1.Minimum;
for (int a = 0; a < numOfTheards; a++)
{
string itemData = lst[a];
threadArray[a].RunWorkerAsync(itemData);
}
}
private void按钮x1\u单击(对象发送者,事件参数e)
{
i=0;
labelX1.Text=“”;
初始化backgoundworkers();
progressBarX1.值=progressBarX1.最小值;
for(int a=0;a
您的问题几乎无法理解…请澄清。我选择了3个项目,其中值文本为2,3,5,因此结果显示为2,2,5
那么预期结果是什么?我选择了3个项目,其中值文本为2,3,5,因此结果显示在标签中为2,2,5。对不起,我的英语不好。这不是我问的问题。预期结果是什么?为什么2,2,5
错误?请解释。我想要的预期结果:2,3,5。意思是选择了Selectitems,因此将有相应的backgroundworker线程执行并向Label显示项目的值文本。我知道我的代码有问题,但我仍然找不到。你能帮我吗?完全删除变量I
。删除行I=0
在后台工作人员的工作方法中,将while
循环替换为private void buttonX1_Click(object sender, EventArgs e)
{
i = 0;
labelX1.Text = "";
InitializeBackgoundWorkers();
progressBarX1.Value = progressBarX1.Minimum;
for (int a = 0; a < numOfTheards; a++)
{
string itemData = lst[a];
threadArray[a].RunWorkerAsync(itemData);
}
}