为什么会这样?
你启动一个线程,它运行一个类.
在该类中有一个for循环,在for循环中有一个"写入消息框"和另一个类.
为什么我把写入和类(首先出现的那个)的命令影响了我的数据的准确性?
(这是在线程正在运行的类中)
int atPDFNumber= 0
foreach (var z in q)
{
atPDFNumber++;
convertToImage(z.FullName);
txtboxtest.BeginInvoke(
((Action)(() => txtboxtest.Text += atPDFNumber.ToString())));
}
Run Code Online (Sandbox Code Playgroud)
那个输出给了我一些重叠的值.输出是
运行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);
Run Code Online (Sandbox Code Playgroud)
为什么会这样?可能是我在ConvertToImage类中使用的外部方法也在运行一个线程..在这种情况下,我如何"暂停"我的线程等待ConvertToImage完成...
其他明智的我不知道为什么这个线程的行为方式呢?
这是竞争条件.你创建一个闭包:
() => txtboxtest.Text += atPDFNumber.ToString()
Run Code Online (Sandbox Code Playgroud)
在引擎盖下,编译器创建了一个非常类的类,如下所示:
class Closure
{
public int? adPDFNumber;
public void Call() {
txtboxtest.Text += atPDFNumber.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
并使用它:
var closure = new Closure();
closure.atPDFNumber = atPDFNumber;
txtboxtest.BeginInvoke(closure.Call);
Run Code Online (Sandbox Code Playgroud)
BeginInvoke实际调用方法在GUI线程中调用,当它发生时,变量atPDFNumber可以增加.您必须在闭包中传递临时变量:
var tmp = atPDFNumber++;
txtboxtest.BeginInvoke(() => txtboxtest.Text += tmp.ToString());
Run Code Online (Sandbox Code Playgroud)
更新: 这种令人困惑的行为在最新版本的C#语言中发生了变化.在C#5中,您可以安全地在lambdas中使用循环变量,并且您的代码示例将正常工作.
| 归档时间: |
|
| 查看次数: |
109 次 |
| 最近记录: |