Winform中C#线程控制的四种常见情况分析

开发 后端
C#线程控制有四种常见情况:启动,通讯,终止以及异常处理。本文总结了一些有关这四种情况的处理建议。

Winform界面中,将事务放在新开的线程中操作是十分有用的做法,因为这样可以增加用户体验,减少耗时。对这些C#线程的控制,常常有下面这四种情况:

1. 启动线程;

2. 线程间通讯;

3. 线程终止;

4. 线程中的异常处理;

下面总结一些上面这些C#线程操作的常用方法。

C#线程控制1. 启动C#线程

◆如果是需要很频繁的开线程,会使用线程池(微软的或自己写的)

◆Thread.Start(参数object);

◆或者用对象提供的BeginXXXX()这种都是异步,也算多线程启动.

C#线程控制2. C#线程间通讯

◆委托,事件这些比较常用,并且对object的多线程处理需要谨慎,可能用到lock(object){}.

◆主要是通过线程同步或者回调方法(或者说是委托)来实现

C#线程控制3. 线程终止

◆线程的终止,用事件AUTORESET之类

◆可以用Thread.ManualEvent().Reset()/Set()/WaitOne()方法来判断和等待

C#线程控制4. 线程中的异常处理

◆线程中的异常通过事件传回到主线程处理

◆还是写log吧,多线程debug比较难,还是逐步log比较好.

用于C#线程通讯的lock关键字

下面的示例演示使用 lock 关键字以及 AutoResetEvent 和 ManualResetEvent 类对主线程和两个辅助线程进行线程同步。

该示例创建两个辅助线程。一个线程生成元素并将它们存储在非线程安全的泛型队列中。有关更多信息,请参见 Queue。另一个线程使用此队列中的项。另外,主线程定期显示队列的内容,因此该队列被三个线程访问。lock 关键字用于同步对队列的访问,以确保队列的状态没有被破坏。

除了用 lock 关键字来阻止同时访问外,还用两个事件对象提供进一步的同步。一个事件对象用来通知辅助线程终止,另一个事件对象由制造者线程用来在有新项添加到队列中时通知使用者线程。这两个事件对象封装在一个名为 SyncEvents 的类中。这使事件可以轻松传递到表示制造者线程和使用者线程的对象。SyncEvents 类是按如下方式定义的:

C# code

  1. using System;   
  2. using System.Threading;   
  3. using System.Collections;   
  4. using System.Collections.Generic;   
  5.  
  6. public class SyncEvents   
  7. {   
  8. public SyncEvents()   
  9. {   
  10.  
  11. _newItemEvent = new AutoResetEvent(false);   
  12. _exitThreadEvent = new ManualResetEvent(false);   
  13. _eventArray = new WaitHandle[2];   
  14. _eventArray[0] = _newItemEvent;   
  15. _eventArray[1] = _exitThreadEvent;   
  16. }   
  17.  
  18. public EventWaitHandle ExitThreadEvent   
  19. {   
  20. get { return _exitThreadEvent; }   
  21. }   
  22. public EventWaitHandle NewItemEvent   
  23. {   
  24. get { return _newItemEvent; }   
  25. }   
  26. public WaitHandle[] EventArray   
  27. {   
  28. get { return _eventArray; }   
  29. }   
  30.  
  31. private EventWaitHandle _newItemEvent;   
  32. private EventWaitHandle _exitThreadEvent;   
  33. private WaitHandle[] _eventArray;   
  34. }   
  35. public class Producer   
  36. {   
  37. public Producer(Queue <int> q, SyncEvents e)   
  38. {   
  39. _queue = q;   
  40. _syncEvents = e;   
  41. }   
  42. // Producer.ThreadRun   
  43. public void ThreadRun()   
  44. {   
  45. int count = 0;   
  46. Random r = new Random();   
  47. while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))   
  48. {   
  49. lock (((ICollection)_queue).SyncRoot)   
  50. {   
  51. while (_queue.Count < 20)   
  52. {   
  53. _queue.Enqueue(r.Next(0,100));   
  54. _syncEvents.NewItemEvent.Set();   
  55. count++;   
  56. }   
  57. }   
  58. }   
  59. Console.WriteLine("Producer thread: produced {0} items", count);   
  60. }   
  61. private Queue <int> _queue;   
  62. private SyncEvents _syncEvents;   
  63. }   
  64.  
  65. public class Consumer   
  66. {   
  67. public Consumer(Queue <int> q, SyncEvents e)   
  68. {   
  69. _queue = q;   
  70. _syncEvents = e;   
  71. }   
  72. // Consumer.ThreadRun   
  73. public void ThreadRun()   
  74. {   
  75. int count = 0;   
  76. while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)   
  77. {   
  78. lock (((ICollection)_queue).SyncRoot)   
  79. {   
  80. int item = _queue.Dequeue();   
  81. }   
  82. count++;   
  83. }   
  84. Console.WriteLine("Consumer Thread: consumed {0} items", count);   
  85. }   
  86. private Queue <int> _queue;   
  87. private SyncEvents _syncEvents;   
  88. }   
  89.  
  90. public class ThreadSyncSample   
  91. {   
  92. private static void ShowQueueContents(Queue <int> q)   
  93. {   
  94. lock (((ICollection)q).SyncRoot)   
  95. {   
  96. foreach (int item in q)   
  97. {   
  98. Console.Write("{0} ", item);   
  99. }   
  100. }   
  101. Console.WriteLine();   
  102. }   
  103.  
  104. static void Main()   
  105. {   
  106. Queue <int> queue = new Queue <int>();   
  107. SyncEvents syncEvents = new SyncEvents();   
  108.  
  109. Console.WriteLine("Configuring worker threads...");   
  110. Producer producer = new Producer(queue, syncEvents);   
  111. Consumer consumer = new Consumer(queue, syncEvents);   
  112. Thread producerThread = new Thread(producer.ThreadRun);   
  113. Thread consumerThread = new Thread(consumer.ThreadRun);   
  114.  
  115. Console.WriteLine("Launching producer and consumer threads...");  
  116. producerThread.Start();   
  117. consumerThread.Start();   
  118.  
  119. for (int i=0; i <4; i++)   
  120. {   
  121. Thread.Sleep(2500);   
  122. ShowQueueContents(queue);   
  123. }   
  124.  
  125. Console.WriteLine("Signaling threads to terminate...");   
  126. syncEvents.ExitThreadEvent.Set();   
  127.  
  128. producerThread.Join();   
  129. consumerThread.Join();   
  130. }   
  131.  
  132. }  
  133.  

【编辑推荐】

  1. C#子线程的控件操作问题解析
  2. C#线程相关问题总结:基本操作及UI控件交互
  3. 学习C#多线程:lock的用法
  4. 总结C#多线程的点点滴滴
  5. 学习C#实现HTTP协议:多线程文件传输
责任编辑:yangsai 来源: CSDN论坛
相关推荐

2009-08-28 16:51:32

C#线程控制

2009-08-26 15:04:35

C#转换

2009-08-20 09:52:31

C#参数类型

2009-08-05 14:09:04

C#日期转换

2009-09-08 17:20:01

C#排序算法

2011-11-24 16:34:39

Java

2021-08-12 11:37:23

数据分析错误

2009-08-17 16:56:51

C#多线程控制进度条

2023-10-30 11:40:36

OOM线程池单线程

2020-06-17 08:31:10

权限控制Spring Secu

2021-07-27 10:49:10

SpringSecurity权限

2009-09-22 14:20:39

C#播放声音

2009-09-17 16:55:58

C#组件设计

2021-06-04 10:45:31

软件架构分布式

2009-08-17 16:41:03

C#多线程控制

2009-08-17 16:29:56

C#多线程控制

2017-04-17 19:31:03

Android多线程

2009-10-13 14:50:19

C#中b=a

2009-09-04 10:42:56

C#流程控制语句

2009-08-17 16:49:46

C#多线程控制
点赞
收藏

51CTO技术栈公众号