标签:
当我们的程序中使用多线程时,对资源的操作是需要特别留意的。如下面的例子:程序中有两个string对象(初始值为空),main函数中分别开启了两个线程去分别设置这两个string对象的值,然后在main函数中打印出这两个字符串的值。代码如下:
static string str1 = string.Empty; static string str2 = string.Empty; static void Main(string[] args) { Thread worker1 = new Thread(SetResource1); Thread worker2 = new Thread(SetResource2); worker1.Start(); worker2.Start(); Console.WriteLine("Result: " + str1 + " " + str2); } static void SetResource1() { Thread.Sleep(TimeSpan.FromSeconds(2)); str1 = "hello"; } static void SetResource2() { Thread.Sleep(TimeSpan.FromSeconds(3)); str2 = "world"; }
程序运行结果:
Result: Press any key to continue . . .
可以看到,main函数中并没有打印出str1和str2的值。因为线程worker1和worker2分别用了2秒钟和3秒钟的时间去设置str1和str2的值。当main函数在打印str1和str2的值的时候,两个工作线程还没有将值设置好,所以main中无法打印str1和str2的值。
为了解决这个问题,我们需要在main函数中等待worker1和worker2均执行完毕后,再打印两个字符串的值,此时我们可以使用Thread类中的Join函数。Join的意思是等待该线程执行完毕,否则阻塞主线程(main函数所在的线程)。
static string str1 = string.Empty; static string str2 = string.Empty; static void Main(string[] args) { Thread worker1 = new Thread(SetResource1); Thread worker2 = new Thread(SetResource2); worker1.Start(); worker2.Start(); worker1.Join(); Console.WriteLine("str1的值已经设置完毕!"); worker2.Join(); Console.WriteLine("str2的值已经设置完毕!"); Console.WriteLine("Result: " + str1 + " " + str2); } static void SetResource1() { Thread.Sleep(TimeSpan.FromSeconds(2)); str1 = "hello"; } static void SetResource2() { Thread.Sleep(TimeSpan.FromSeconds(3)); str2 = "world"; }
运行结果如下:
str1的值已经设置完毕! str2的值已经设置完毕! Result: hello world Press any key to continue . . .
通过代码可以看到,我们在main函数中分别调用了worker1和worker2的Join方法,结果是woker1和worker2分别执行完后main函数才继续往下执行,否则main函数处于阻塞(等待)状态。Join还有另外的重载方法,可以指定等待的时间上限(如3秒钟),如果超过这个等待时间上限main函数依然往下执行。
笔者在工作中遇到这样一个场景:网站的代码需要通过ADO.NET调用后台的多个存储过程,而每个存储过程均会比较耗时,所以我们使用了多线程技术去分别调用存储过程。然后在代码中对每个线程调用Join方法,等待每个存储过程结果均返回后,再将数据封装传到前台UI(User Interface)。这样既提高了程序的运行效率,又保证了数据的完整性。
标签:
原文地址:http://www.cnblogs.com/kuillldan/p/5077645.html