1、以协作方式取消线程
using System; using System.Threading; public class ServerClass { public static void StaticMethod(object obj) { CancellationToken ct = (CancellationToken)obj; Console.WriteLine("ServerClass.StaticMethod is running on another thread."); // Simulate work that can be canceled. while (!ct.IsCancellationRequested) { Thread.SpinWait(50000); } Console.WriteLine("The worker thread has been canceled. Press any key to exit."); Console.ReadKey(true); } } public class Simple { public static void Main() { // The Simple class controls access to the token source. CancellationTokenSource cts = new CancellationTokenSource(); Console.WriteLine("Press 'C' to terminate the application...\n"); // Allow the UI thread to capture the token source, so that it // can issue the cancel command. Thread t1 = new Thread(() => { if (Console.ReadKey(true).KeyChar.ToString().ToUpperInvariant() == "C") cts.Cancel(); } ); // ServerClass sees only the token, not the token source. Thread t2 = new Thread(new ParameterizedThreadStart(ServerClass.StaticMethod)); // Start the UI thread. t1.Start(); // Start the worker thread and pass it the token. t2.Start(cts.Token); t2.Join(); cts.Dispose(); } } // The example displays the following output: // Press 'C' to terminate the application... // // ServerClass.StaticMethod is running on another thread. // The worker thread has been canceled. Press any key to exit.
2、通过轮询侦听取消请求
using System; using System.Threading; using System.Threading.Tasks; public struct Rectangle { public int columns; public int rows; } class CancelByPolling { static void Main() { var tokenSource = new CancellationTokenSource(); // Toy object for demo purposes Rectangle rect = new Rectangle() { columns = 1000, rows = 500 }; // Simple cancellation scenario #1. Calling thread does not wait // on the task to complete, and the user delegate simply returns // on cancellation request without throwing. Task.Run(() => NestedLoops(rect, tokenSource.Token), tokenSource.Token); // Simple cancellation scenario #2. Calling thread does not wait // on the task to complete, and the user delegate throws // OperationCanceledException to shut down task and transition its state. // Task.Run(() => PollByTimeSpan(tokenSource.Token), tokenSource.Token); Console.WriteLine("Press 'c' to cancel"); if (Console.ReadKey(true).KeyChar == 'c') { tokenSource.Cancel(); Console.WriteLine("Press any key to exit."); } Console.ReadKey(); tokenSource.Dispose(); } static void NestedLoops(Rectangle rect, CancellationToken token) { for (int x = 0; x < rect.columns && !token.IsCancellationRequested; x++) { for (int y = 0; y < rect.rows; y++) { // Simulating work. Thread.SpinWait(5000); Console.Write("{0},{1} ", x, y); } // Assume that we know that the inner loop is very fast. // Therefore, checking once per row is sufficient. if (token.IsCancellationRequested) { // Cleanup or undo here if necessary... Console.WriteLine("\r\nCancelling after row {0}.", x); Console.WriteLine("Press any key to exit."); // then... break; // ...or, if using Task: // token.ThrowIfCancellationRequested(); } } } }
3、注册取消请求的回调 token.Register(() => wc.CancelAsync())
using System; using System.Net; using System.Threading; using System.Threading.Tasks; class CancelWithCallback { static void Main() { var cts = new CancellationTokenSource(); var token = cts.Token; // Start cancelable task. Task t = Task.Run( () => { WebClient wc = new WebClient(); // Create an event handler to receive the result. wc.DownloadStringCompleted += (obj, e) => { // Check status of WebClient, not external token. if (!e.Cancelled) { Console.WriteLine("The download has completed:\n"); Console.WriteLine(e.Result + "\n\nPress any key."); } else { Console.WriteLine("The download was canceled."); } }; // Do not initiate download if the external token // has already been canceled. if (!token.IsCancellationRequested) { // Register the callback to a method that can unblock. using (CancellationTokenRegistration ctr = token.Register(() => wc.CancelAsync())) { Console.WriteLine("Starting request\n"); wc.DownloadStringAsync(new Uri("http://www.contoso.com")); } } }, token); Console.WriteLine("Press 'c' to cancel.\n"); char ch = Console.ReadKey().KeyChar; Console.WriteLine(); if (ch == 'c') cts.Cancel(); Console.WriteLine("Press any key to exit."); Console.ReadKey(); cts.Dispose(); } }
4、侦听具有等待句柄的取消请求
using System; using System.Threading; using System.Threading.Tasks; class CancelOldStyleEvents { // Old-style MRE that doesn't support unified cancellation. static ManualResetEvent mre = new ManualResetEvent(false); static void Main() { var cts = new CancellationTokenSource(); // Pass the same token source to the delegate and to the task instance. Task.Run(() => DoWork(cts.Token), cts.Token); Console.WriteLine("Press s to start/restart, p to pause, or c to cancel."); Console.WriteLine("Or any other key to exit."); // Old-style UI thread. bool goAgain = true; while (goAgain) { char ch = Console.ReadKey(true).KeyChar; switch (ch) { case 'c': cts.Cancel(); break; case 'p': mre.Reset(); break; case 's': mre.Set(); break; default: goAgain = false; break; } Thread.Sleep(100); } cts.Dispose(); } static void DoWork(CancellationToken token) { while (true) { // 没有收到信号 将等待 int eventThatSignaledIndex = WaitHandle.WaitAny(new WaitHandle[] { mre, token.WaitHandle }, new TimeSpan(0, 0, 20)); // Were we canceled while waiting? if (eventThatSignaledIndex == 1) { Console.WriteLine("The wait operation was canceled."); throw new OperationCanceledException(token); } // Were we canceled while running? else if (token.IsCancellationRequested) { Console.WriteLine("I was canceled while running."); token.ThrowIfCancellationRequested(); } // Did we time out? else if (eventThatSignaledIndex == WaitHandle.WaitTimeout) { Console.WriteLine("I timed out."); break; } else { Console.Write("Working... "); // Simulating work. Thread.SpinWait(5000000); } } } }
5、侦听多个取消请求
此示例展示了如何同时侦听两个取消令牌,以便在其中任意一个令牌发出请求时取消操作。
//创建一个新token 合并内部和外部的tokens
CancellationTokenSource linkedCts =
CancellationTokenSource.CreateLinkedTokenSource(internalToken, externalToken)
using System; using System.Threading; using System.Threading.Tasks; class LinkedTokenSourceDemo { static void Main() { WorkerWithTimer worker = new WorkerWithTimer(); CancellationTokenSource cts = new CancellationTokenSource(); // Task for UI thread, so we can call Task.Wait wait on the main thread. Task.Run(() => { Console.WriteLine("Press 'c' to cancel within 3 seconds after work begins."); Console.WriteLine("Or let the task time out by doing nothing."); if (Console.ReadKey(true).KeyChar == 'c') cts.Cancel(); }); // Let the user read the UI message. Thread.Sleep(1000); // Start the worker task. Task task = Task.Run(() => worker.DoWork(cts.Token), cts.Token); try { task.Wait(cts.Token); } catch (OperationCanceledException e) { if (e.CancellationToken == cts.Token) Console.WriteLine("Canceled from UI thread throwing OCE."); } catch (AggregateException ae) { Console.WriteLine("AggregateException caught: " + ae.InnerException); foreach (var inner in ae.InnerExceptions) { Console.WriteLine(inner.Message + inner.Source); } } Console.WriteLine("Press any key to exit."); Console.ReadKey(); cts.Dispose(); } } class WorkerWithTimer { CancellationTokenSource internalTokenSource = new CancellationTokenSource(); CancellationToken internalToken; CancellationToken externalToken; Timer timer; public WorkerWithTimer() { internalTokenSource = new CancellationTokenSource(); internalToken = internalTokenSource.Token; // A toy cancellation trigger that times out after 3 seconds // if the user does not press 'c'. timer = new Timer(new TimerCallback(CancelAfterTimeout), null, 3000, 3000); } public void DoWork(CancellationToken externalToken) { // Create a new token that combines the internal and external tokens. //创建一个新token 合并内部和外部的tokens this.internalToken = internalTokenSource.Token; this.externalToken = externalToken; using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(internalToken, externalToken)) { try { DoWorkInternal(linkedCts.Token); } catch (OperationCanceledException) { if (internalToken.IsCancellationRequested) { Console.WriteLine("Operation timed out."); } else if (externalToken.IsCancellationRequested) { Console.WriteLine("Cancelling per user request."); externalToken.ThrowIfCancellationRequested(); } } } } private void DoWorkInternal(CancellationToken token) { for (int i = 0; i < 1000; i++) { if (token.IsCancellationRequested) { // We need to dispose the timer if cancellation // was requested by the external token. timer.Dispose(); // Throw the exception. token.ThrowIfCancellationRequested(); } // Simulating work. Thread.SpinWait(7500000); Console.Write("working... "); } } public void CancelAfterTimeout(object state) { Console.WriteLine("\r\nTimer fired."); internalTokenSource.Cancel(); timer.Dispose(); } }
相关推荐
` 这是最为决绝的退出方式,它会立即停止所有线程,包括主线程和其他托管线程,从而彻底结束程序。一般情况下,只有在确保所有必要的清理工作已完成,且不需要等待任何线程完成时才使用此方法。 5. `Application....
在Windows API中,主要有以下几种钩子: 1. **WH_MOUSE_LL**:低级鼠标钩子,用于捕获所有线程的鼠标消息。 2. **WH_KEYBOARD_LL**:低级键盘钩子,同样捕获所有线程的键盘消息。 在VB.NET或C#中,我们需要使用P/...
这个程序是用C#编程语言编写的,C#是一种广泛应用于Windows平台开发的面向对象的编程语言,属于.NET框架的一部分。.NET框架为开发者提供了丰富的类库和工具,简化了软件开发过程。 在描述中,作者提到程序“不好”...
5. **多线程**:考虑到定时器可能在后台线程中运行,而关机操作可能需要在主线程上执行,因此需要理解并正确处理多线程环境,以确保程序的正确性。 6. **权限管理**:执行关机操作可能需要管理员权限,因此程序启动...
3. 取消功能:用户应能随时取消已设置的定时关机任务。 4. 服务模式:为了让软件在后台持续运行,开发者可能选择将其设计为Windows服务,即使用户注销或关闭所有应用程序,定时任务仍能继续执行。 总之,【定时关机...
而属性提供了一种更安全的方式访问字段,通常通过getter和setter方法实现。 #### 二十九、.NET Framework支持封装的方式 - **封装支持**:.NET Framework通过类和接口的定义、访问修饰符如public、private等来支持...
在Windows API中,有几个函数可以用来防止或取消关机,如`SetConsoleCtrlHandler`用于处理控制台事件,`CancelShutdown`用于取消已启动的关机过程。然而,最常用的是`SetWindowLong`和`...
C#是由微软开发的一种面向对象的编程语言,广泛应用于Windows平台的应用程序开发。在这个定时关机小助手中,C#被用来构建用户界面、处理用户输入和执行关机操作。C#支持事件驱动编程,使得用户界面可以响应用户的...
PHP是一种广泛使用的开源脚本语言,尤其适用于Web开发,与HTML、CSS、JavaScript等技术结合,能构建动态、交互性强的网站。本指南将详细介绍如何在Windows系统上搭建PHP运行环境,包括PHP、MySQL和Apache服务器的...
如前所述,我是一个狮子座男人,一度我认为学习Java会使我看起来与众不同,可是几个月以后我放弃了这个选择,我看了论坛里关于这两种语言孰优孰劣的讨论,最终选择了C#,请不要问我为何做出这样的选择,很多人认为...
14 <br>0028 “///”符号的使用技巧 14 <br>0029 使用注释取消程序语句的执行 15 <br>2.2 语句 15 <br>0030 跳转语句GOTO的使用 15 <br>0031 Continue语句的使用 16 <br>0032 Break...