作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
为什么会这样?
你启动一个线程,它运行一个类。
在该类中有一个 for 循环,在 for 循环中有一个“写入消息框”和另一个类。
为什么我放置写入和类的顺序(哪个先发生)会影响我的数据的准确性?
(这是线程运行的类内部)
int atPDFNumber= 0
foreach (var z in q)
{
atPDFNumber++;
convertToImage(z.FullName);
txtboxtest.BeginInvoke(
((Action)(() => txtboxtest.Text += atPDFNumber.ToString())));
}
那个输出给了我一些重叠的值。输出是
运行 1 : 1 2 3 4 5 6 7 8 9 10 11 12 13 14
运行 2 : 1 3 3 4 5 6 7 8 9 10 11 12 13 14
运行 2:1 2 3 4 5 6 7 8 9 11 11 12 13 14
这里以正确的顺序运行它们
foreach (var z in q)
{
atPDFNumber++;
txtboxtest.BeginInvoke(
((Action)(() => txtboxtest.Text += atPDFNumber.ToString())));
convertToImage(z.FullName);
为什么会这样?可能是我在 ConvertToImage 类中使用的外部方法也在运行一个线程。在这种情况下,我将如何“暂停”我的线程以等待 ConvertToImage 完成......
除此之外,我不知道为什么这个线程会按照它的方式运行?
最佳答案
这是一个竞争条件。你创建一个闭包:
() => txtboxtest.Text += atPDFNumber.ToString()
在幕后,编译器创建了一个匿名类,像这样:
class Closure
{
public int? adPDFNumber;
public void Call() {
txtboxtest.Text += atPDFNumber.ToString();
}
}
并使用它:
var closure = new Closure();
closure.atPDFNumber = atPDFNumber;
txtboxtest.BeginInvoke(closure.Call);
BeginInvoke 实际上在 GUI 线程中调用方法 Call,当它发生时,变量 atPDFNumber 可能已经递增。您必须在闭包中传递临时变量:
var tmp = atPDFNumber++;
txtboxtest.BeginInvoke(() => txtboxtest.Text += tmp.ToString());
更新:这种令人困惑的行为在最新版本的 C# 语言中有所改变。在 C# 5 中,您可以在 lambda 中安全地使用循环变量,并且您的代码示例将正常工作。
关于c# - 如何在线程中捕获正确的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12742662/
我是一名优秀的程序员,十分优秀!