VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > 简明python教程 >
  • C#线程 入门(2)

1
2
3
4
5
6
7
8
9
10
11
static void Main()
{
  Thread t = new Thread (Print);
  t.Start ("Hello from t!");
}
 
static void Print (object messageObj)
{
  string message = (string) messageObj;   // We need to cast here
  Console.WriteLine (message);
}

 

之所以可行,是因为Thread的构造函数被重载为接受两个委托之一:

1
2
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart (object obj);

  

ParameterizedThreadStart的局限性在于它仅接受一个参数。而且由于它是object类型的,因此通常需要强制转换。

Lambda表达式和捕获的变量

如我们所见,lambda表达式是将数据传递到线程的最强大的方法。但是,您必须小心在启动线程后意外修改捕获的变量,因为这些变量是共享的。例如,考虑以下内容:
1
2
for (int i = 0; i < 10; i++)
  new Thread (() => Console.Write (i)).Start();

  输出是不确定的!这是一个典型的结果:

0223557799

问题在于,i变量在循环的整个生命周期中都指向相同的内存位置。因此,每个线程都会在变量上调用Console.Write,该变量的值可能会随着运行而改变!

 

这类似于我们在C#4.0的第八章“捕获变量”中描述的问题。问题不在于多线程,而是与C#捕获变量的规则有关(在for和foreach循环的情况下这是不希望的)。

 

 解决方案是使用如下临时变量:

1
2
3
4
5
for (int i = 0; i < 10; i++)
{
  int temp = i;
  new Thread (() => Console.Write (temp)).Start();
}

  

现在,可变温度是每个循环迭代的局部变量。因此,每个线程捕获一个不同的内存位置,这没有问题。我们可以通过以下示例更简单地说明早期代码中的问题:

1
2
3
4
5
6
7
8
string text = "t1";
Thread t1 = new Thread ( () => Console.WriteLine (text) );
 
text = "t2";
Thread t2 = new Thread ( () => Console.WriteLine (text) );
 
t1.Start();
t2.Start();

相关教程