[英]ParallelFor | Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on
[英]Cross-thread operation not valid: Control 'lbDatabase' accessed from a thread other than the thread it was created on
我正在使用指纹,需要进行此操作,但出现错误,并且不知道如何解决
private void doVerify(object sender, DoWorkEventArgs args)
{
VerificationResult verificationResult = new VerificationResult();
for (int i = 0; i < lbDatabase.Items.Count || verificationResult.score > 0; i++)
{
lbDatabase.Invoke(new MethodInvoker(delegate { lbDatabase.SelectedItem = i; }));
verificationResult.score = _engine.Verify(((CData)lbDatabase.SelectedItem).EngineUser, 20000, out verificationResult.engineStatus);
}
args.Result = verificationResult;
}
错误:跨线程操作无效:从不是在其上创建线程的线程访问控件“ lbDatabase”
错误很明显。 您正在其他线程上运行,因此无法与控件进行交互。 这意味着访问lbDatabase.Items.Count
已结束。
相反,如果您:
lbDatabase.Invoke((MethodInvoker)(() => {
VerificationResult verificationResult = new VerificationResult();
for (int i = 0; i < lbDatabase.Items.Count || verificationResult.score > 0; i++)
{
lbDatabase.SelectedItem = i;
verificationResult.score = _engine.Verify(((CData)lbDatabase.SelectedItem).EngineUser, 20000, out verificationResult.engineStatus);
}
args.Result = verificationResult;
}));
那么您可能会重新营业。 现在,对控件的所有访问都已排队等待在UI线程上运行(并且您不再需要在循环中间使用Invoke
切换上下文了……代价很高)。
您在代码中有三个位置可以访问lbDatabase
。
lbDatabase.Items.Count
lbDatabase.SelectedItem = i
lbDatabase.SelectedItem
我假设在第二本上,您打算编写lbDatabase.SelectedIndex = i
。
您正在调用的仅第二个。 因此,其他两个正在后台工作线程上运行。 这就是为什么您得到错误。
对UI元素的所有访问(读写)都需要在UI线程上完成。
现在,由于您尝试使用后台工作人员执行此操作,因此您有一种方法可以冻结UI(如果它仅在UI线程上运行)。 因此,您需要访问控件的部件才能在UI上运行,而其他所有部件都可以在后台线程上运行。
不过,下一个问题是,调用lbDatabase.Invoke(new MethodInvoker(delegate { lbDatabase.SelectedItem = i; }));
将指令推送到UI,但是不能保证代码会立即运行-实际上,整个循环可能会运行并将所有调用排队。 您显然希望它同步发生,但是那不会发生。
看你的代码,你显然只希望访问所有的CData
项目上lbDatabase
列表框中。 有一种非常简单的方法可以完成这项工作。
致电后台工作人员时只需尝试以下操作:
backgroundWorker1.RunWorkerAsync(lbDatabase.Items.Cast<CData>().ToArray());
然后将doVerify
更改为此:
private void doVerify(object sender, DoWorkEventArgs args)
{
CData[] items = (CData[])args.Argument;
VerificationResult verificationResult = new VerificationResult();
for (int i = 0; i < items.Length || verificationResult.score > 0; i++)
{
verificationResult.score = _engine.Verify(items[i].EngineUser, 20000, out verificationResult.engineStatus);
}
args.Result = verificationResult;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.