Task 类 多线程
Task 类
定义
- 命名空间: System.Threading.Tasks
- 程序集: System.Runtime.dll
- 表示一个异步操作
public class Task : IAsyncResult, IDisposable
- 继承 Object->Task
注解
类 Task 表示不返回值且通常异步执行的单个操作。 Task对象是.NET Framework 4 中首次引入的基于任务的异步模式的核心组件之一。 由于对象执行 Task 的工作通常在线程池线程上异步执行,而不是在主应用程序线程上同步执行,因此可以使用 Status 属性以及 IsCanceled、 IsCompleted和 IsFaulted 属性来确定任务的状态。 大多数情况下,lambda 表达式用于指定任务要执行的工作。
对于返回值的操作,请使用 Task<TResult> 类。
本部分内容:
创建和执行任务
等待一个或多个任务完成
任务和区域性
面向调试器开发人员
任务实例化(创建任务的方法)
由于任务 t4
以同步方式执行,因此它会在主应用程序线程上执行。 其余任务通常在一个或多个线程池线程上异步执行。
注意:使用 Task.Factory.StartNew() 和 Task.Run(() =>{}) 创建的任务会立即执行
任务的创建和执行分离,请先 new Task(),然后调用任务的Start()
static void Main(string[] args) { Action<object?> action = (object obj) => { Console.WriteLine($"Task={Task.CurrentId},obj={obj}," + $"Thread={Thread.CurrentThread.ManagedThreadId}"); }; //1.new创建一个任务,但并不会立即执行,除非调用 Start()方法 Task t1 = new(action, "alpha_T1");//alpha_T1 为传给委托的参数 //2.使用StartNew方法创建一个任务并立即执行 Task t2 = Task.Factory.StartNew(action, "beta_T2");//beta_T2 为传给委托的参数 //阻塞主线程以证明 t2 正在执行 t2.Wait(); //执行 t1 t1.Start(); Console.WriteLine("t1 已开始执行. (Main Thread={0})", Thread.CurrentThread.ManagedThreadId); //等待t1任务执行完成 t1.Wait(); //3.使用Task.Run 创建任务,立即执行 string taskData = "delta_T3"; Task t3 = Task.Run(() => { Console.WriteLine("Task={0}, obj={1}, Thread={2}", Task.CurrentId, taskData, Thread.CurrentThread.ManagedThreadId); }); t3.Wait(); Task t4 = new Task(action, "gamma_T4"); //同步运行,即在主线程上运行 t4.RunSynchronously(); t4.Wait(); Console.ReadKey(); }
等
待一个或多个任务完成
应用程序的逻辑可能要求调用线程仅在一个或多个任务完成执行时继续执行。 可以通过调用 Wait
方法来等待一个或多个任务完成,来同步调用线程及其启动的异步任务的执行。
若要等待单个任务完成,可以调用其 Task.Wait 方法。 对 方法的 Wait 调用会阻止调用线程,直到单个类实例完成执行。
Task taskA = Task.Run(() => { Thread.Sleep(2000); }); Console.WriteLine("taskA Status:{0}", taskA.Status); try { taskA.Wait();//等待一个任务完成 Console.WriteLine("taskA Status:{0}", taskA.Status); } catch (AggregateException) { Console.WriteLine("Exception in taskA."); }
有条件地等待任务完成。 Wait(Int32)和 Wait(TimeSpan) 方法会阻止调用线程,直到任务完成或超时间隔过(以先到者为准)。 由于以下示例启动一个休眠两秒但定义一秒超时值的任务,调用线程将一直阻止,直到超时到期和任务完成执行。
// Wait on a single task with a timeout specified. Task taskA = Task.Run( () => Thread.Sleep(2000)); try { taskA.Wait(1000); // Wait for 1 second. bool completed = taskA.IsCompleted; Console.WriteLine("Task A completed: {0}, Status: {1}", completed, taskA.Status); if (! completed) Console.WriteLine("Timed out before task A completed."); } catch (AggregateException) { Console.WriteLine("Exception in taskA."); }
还可以通过调用 Wait(CancellationToken) 和 Wait(Int32, CancellationToken) 方法提供取消令牌。 如果在执行方法时令牌的 IsCancellationRequested 属性为 true
或 变为 true
,则 该方法将OperationCanceledExceptionWait引发 。
可能希望等待一系列执行任务中的第一个完成,但不关心它是哪个任务。 为此,可以调用 方法的重载 Task.WaitAny 之一
var tasks = new Task[3]; var rnd = new Random(); for (int ctr = 0; ctr <= 2; ctr++) tasks[ctr] = Task.Run( () => Thread.Sleep(rnd.Next(500, 3000))); try { int index = Task.WaitAny(tasks); Console.WriteLine("Task #{0} completed first.\n", tasks[index].Id); Console.WriteLine("Status of all tasks:"); foreach (var t in tasks) Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status); } catch (AggregateException) { Console.WriteLine("An exception occurred."); }
还可以通过调用 WaitAll 方法等待所有一系列任务完成