ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-Threading(线程处理) |
1.A,示例(Sample) 返回顶部 |
“线程处理”示例
本示例演示了下面的线程处理技术。有关更多信息,请参见线程处理(C# 编程指南) 。
- 创建、启动和终止线程
- 使用线程池
- 线程同步和互交
安全说明 |
---|
提供此代码示例是为了阐释一个概念,它并不代表最安全的编码实践,因此不应在应用程序或网站中使用此代码示例。对于因将此代码示例用于其他用途而出现的偶然或必然的损害,Microsoft 不承担任何责任。 |
在 Visual Studio 中生成并运行“线程处理”示例
- 在“解决方案资源管理器”中,右击“ThreadStartStop”项目并单击“设为启动项目”。
- 在“调试”菜单上,单击“开始执行(不调试)”。
- 对于 ThreadPool 和 ThreadSync,分别重复上述步骤。
从命令行生成并运行“线程”示例
- 使用“更改目录”命令转到“Threads”目录。
- 键入以下命令:
cd ThreadStartStop csc ThreadStartStop.cs ThreadStartStop
- 键入以下命令:
cd ..\ThreadPool csc ThreadPool.cs ThreadPool
- 键入以下命令:
cd ..\ThreadSync csc ThreadSync.cs ThreadSync
1.B,ThreadStartStop 示例代码(Sample Code)返回顶部 |
1.B.1, ThreadStartStop.cs
// 版权所有(C) Microsoft Corporation。保留所有权利。 // 此代码的发布遵从 // Microsoft 公共许可(MS-PL,http://opensource.org/licenses/ms-pl.html)的条款。 // //版权所有(C) Microsoft Corporation。保留所有权利。 using System; using System.Threading; public class Worker { // 启动线程时调用此方法。 public void DoWork() { while (!_shouldStop) { Console.WriteLine("worker thread: working..."); } Console.WriteLine("worker thread: terminating gracefully."); } public void RequestStop() { _shouldStop = true; } // Volatile 用于向编译器提示此数据 // 成员将由多个线程访问。 private volatile bool _shouldStop; } public class WorkerThreadExample { static void Main() { // 创建线程对象。这不会启动该线程。 Worker workerObject = new Worker(); Thread workerThread = new Thread(workerObject.DoWork); // 启动辅助线程。 workerThread.Start(); Console.WriteLine("main thread: Starting worker thread..."); // 循环直至辅助线程激活。 while (!workerThread.IsAlive); // 为主线程设置 1 毫秒的休眠, // 以使辅助线程完成某项工作。 Thread.Sleep(1); // 请求辅助线程自行停止: workerObject.RequestStop(); // 使用 Join 方法阻塞当前线程, // 直至对象的线程终止。 workerThread.Join(); Console.WriteLine("main thread: Worker thread has terminated."); } }
1.B.2,
1.B.EXE,
main thread: Starting worker thread... worker thread: working... worker thread: working... worker thread: working... worker thread: working... worker thread: working... worker thread: working... worker thread: working... worker thread: working... worker thread: terminating gracefully. main thread: Worker thread has terminated. 请按任意键继续. . .
1.B
1.B,ThreadPool 示例代码2(Sample Code)返回顶部 |
1.B.1, ThreadPool.cs
// 版权所有(C) Microsoft Corporation。保留所有权利。 // 此代码的发布遵从 // Microsoft 公共许可(MS-PL,http://opensource.org/licenses/ms-pl.html)的条款。 // //版权所有(C) Microsoft Corporation。保留所有权利。 using System; using System.Threading; // Fibonacci 类为使用辅助 // 线程执行长时间的 Fibonacci(N) 计算提供了一个接口。 // N 是为 Fibonacci 构造函数提供的,此外还提供了 // 操作完成时对象发出的事件信号。 // 然后,可以使用 FibOfN 属性来检索结果。 public class Fibonacci { public Fibonacci(int n, ManualResetEvent doneEvent) { _n = n; _doneEvent = doneEvent; } // 供线程池使用的包装方法。 public void ThreadPoolCallback(Object threadContext) { int threadIndex = (int)threadContext; Console.WriteLine("thread {0} started...", threadIndex); _fibOfN = Calculate(_n); Console.WriteLine("thread {0} result calculated...", threadIndex); _doneEvent.Set(); } // 计算第 N 个斐波纳契数的递归方法。 public int Calculate(int n) { if (n <= 1) { return n; } else { return Calculate(n - 1) + Calculate(n - 2); } } public int N { get { return _n; } } private int _n; public int FibOfN { get { return _fibOfN; } } private int _fibOfN; ManualResetEvent _doneEvent; } public class ThreadPoolExample { static void Main() { const int FibonacciCalculations = 10; // 每个 Fibonacci 对象使用一个事件 ManualResetEvent[] doneEvents = new ManualResetEvent[FibonacciCalculations]; Fibonacci[] fibArray = new Fibonacci[FibonacciCalculations]; Random r = new Random(); // 使用 ThreadPool 配置和启动线程: Console.WriteLine("launching {0} tasks...", FibonacciCalculations); for (int i = 0; i < FibonacciCalculations; i++) { doneEvents[i] = new ManualResetEvent(false); Fibonacci f = new Fibonacci(r.Next(20,40), doneEvents[i]); fibArray[i] = f; ThreadPool.QueueUserWorkItem(f.ThreadPoolCallback, i); } // 等待池中的所有线程执行计算... WaitHandle.WaitAll(doneEvents); Console.WriteLine("Calculations complete."); // 显示结果... for (int i= 0; i<FibonacciCalculations; i++) { Fibonacci f = fibArray[i]; Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN); } } }
1.B.2,
1.B.EXE,
launching 10 tasks... thread 0 started... thread 1 started... thread 1 result calculated... thread 2 started... thread 2 result calculated... thread 3 started... thread 0 result calculated... thread 4 started... thread 4 result calculated... thread 5 started... thread 5 result calculated... thread 6 started... thread 6 result calculated... thread 7 started... thread 7 result calculated... thread 8 started... thread 8 result calculated... thread 9 started... thread 3 result calculated... thread 9 result calculated... Calculations complete. Fibonacci(27) = 196418 Fibonacci(23) = 28657 Fibonacci(21) = 10946 Fibonacci(38) = 39088169 Fibonacci(25) = 75025 Fibonacci(25) = 75025 Fibonacci(37) = 24157817 Fibonacci(27) = 196418 Fibonacci(29) = 514229 Fibonacci(37) = 24157817 请按任意键继续. . .
1.B,
1.B,ThreadSync 示例代码3(Sample Code)返回顶部 |
1.B.1, ThreadSync.cs
// 版权所有(C) Microsoft Corporation。保留所有权利。 // 此代码的发布遵从 // Microsoft 公共许可(MS-PL,http://opensource.org/licenses/ms-pl.html)的条款。 // //版权所有(C) Microsoft Corporation。保留所有权利。 using System; using System.Threading; using System.Collections; using System.Collections.Generic; // 将线程同步事件封装在此类中, // 以便于将这些事件传递给 Consumer 和 // Producer 类。 public class SyncEvents { public SyncEvents() { // AutoResetEvent 用于“新项”事件,因为 // 我们希望每当使用者线程响应此事件时, // 此事件就会自动重置。 _newItemEvent = new AutoResetEvent(false); // ManualResetEvent 用于“退出”事件,因为 // 我们希望发出此事件的信号时有多个线程响应。 // 如果使用 AutoResetEvent,事件 // 对象将在单个线程作出响应之后恢复为 // 未发信号的状态,而其他线程将 // 无法终止。 _exitThreadEvent = new ManualResetEvent(false); // 这两个事件也放在一个 WaitHandle 数组中,以便 // 使用者线程可以使用 WaitAny 方法 // 阻塞这两个事件。 _eventArray = new WaitHandle[2]; _eventArray[0] = _newItemEvent; _eventArray[1] = _exitThreadEvent; } // 公共属性允许对事件进行安全访问。 public EventWaitHandle ExitThreadEvent { get { return _exitThreadEvent; } } public EventWaitHandle NewItemEvent { get { return _newItemEvent; } } public WaitHandle[] EventArray { get { return _eventArray; } } private EventWaitHandle _newItemEvent; private EventWaitHandle _exitThreadEvent; private WaitHandle[] _eventArray; } // Producer 类(使用一个辅助线程) // 将项异步添加到队列中,共添加 20 个项。 public class Producer { public Producer(Queue<int> q, SyncEvents e) { _queue = q; _syncEvents = e; } public void ThreadRun() { int count = 0; Random r = new Random(); while (!_syncEvents.ExitThreadEvent.WaitOne(0, false)) { lock (((ICollection)_queue).SyncRoot) { while (_queue.Count < 20) { _queue.Enqueue(r.Next(0, 100)); _syncEvents.NewItemEvent.Set(); count++; } } } Console.WriteLine("Producer thread: produced {0} items", count); } private Queue<int> _queue; private SyncEvents _syncEvents; } // Consumer 类通过自己的辅助线程使用队列 // 中的项。Producer 类使用 NewItemEvent // 将新项通知 Consumer 类。 public class Consumer { public Consumer(Queue<int> q, SyncEvents e) { _queue = q; _syncEvents = e; } public void ThreadRun() { int count = 0; while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1) { lock (((ICollection)_queue).SyncRoot) { int item = _queue.Dequeue(); } count++; } Console.WriteLine("Consumer Thread: consumed {0} items", count); } private Queue<int> _queue; private SyncEvents _syncEvents; } public class ThreadSyncSample { private static void ShowQueueContents(Queue<int> q) { // 对集合进行枚举本来就不是线程安全的, // 因此在整个枚举过程中锁定集合以防止 // 使用者和制造者线程修改内容 // 是绝对必要的。(此方法仅由 // 主线程调用。) lock (((ICollection)q).SyncRoot) { foreach (int i in q) { Console.Write("{0} ", i); } } Console.WriteLine(); } static void Main() { // 配置结构,该结构包含线程同步 // 所需的事件信息。 SyncEvents syncEvents = new SyncEvents(); // 泛型队列集合用于存储要制造和使用的 // 项。此例中使用的是“int”。 Queue<int> queue = new Queue<int>(); // 创建对象,一个用于制造项,一个用于 // 使用项。将队列和线程同步事件传递给 // 这两个对象。 Console.WriteLine("Configuring worker threads..."); Producer producer = new Producer(queue, syncEvents); Consumer consumer = new Consumer(queue, syncEvents); // 为制造者对象和使用者对象创建线程 // 对象。此步骤并不创建或启动 // 实际线程。 Thread producerThread = new Thread(producer.ThreadRun); Thread consumerThread = new Thread(consumer.ThreadRun); // 创建和启动两个线程。 Console.WriteLine("Launching producer and consumer threads..."); producerThread.Start(); consumerThread.Start(); // 为制造者线程和使用者线程设置 10 秒的运行时间。 // 使用主线程(执行此方法的线程) // 每隔 2.5 秒显示一次队列内容。 for (int i = 0; i < 4; i++) { Thread.Sleep(2500); ShowQueueContents(queue); } // 向使用者线程和制造者线程发出终止信号。 // 这两个线程都会响应,由于 ExitThreadEvent 是 // 手动重置的事件,因此除非显式重置,否则将保持“设置”。 Console.WriteLine("Signaling threads to terminate..."); syncEvents.ExitThreadEvent.Set(); // 使用 Join 阻塞主线程,首先阻塞到制造者线程 // 终止,然后阻塞到使用者线程终止。 Console.WriteLine("main thread waiting for threads to finish..."); producerThread.Join(); consumerThread.Join(); } }
1.B.2,
1.B.EXE,
Configuring worker threads... Launching producer and consumer threads... 87 65 95 1 77 97 21 64 77 43 50 63 4 99 84 29 5 26 35 41 15 71 91 26 56 21 21 18 51 15 9 25 50 5 65 82 76 99 99 23 41 24 6 80 37 95 87 52 83 96 86 67 34 47 10 42 44 17 40 10 44 38 75 35 85 85 92 33 25 33 86 48 12 99 7 92 36 17 Signaling threads to terminate... main thread waiting for threads to finish... Producer thread: produced 2015587 items Consumer Thread: consumed 2015568 items 请按任意键继续. . .
1.B,
1.C,下载地址(Free Download)返回顶部 |
作者:ylbtech 出处:http://ylbtech.cnblogs.com/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 |
时间: 2024-10-12 22:42:41