- Task的基本概念
- 定义:在C#中,
Task
是用于表示一个异步操作的抽象。它是一种轻量级的、可等待的对象,允许你在不阻塞当前线程的情况下执行操作。Task
类型位于System.Threading.Tasks
命名空间中。 - 用途:可以用来处理各种耗时的操作,如文件I/O、网络请求、复杂的计算等,从而提高应用程序的响应性和性能。例如,在一个图形用户界面(GUI)应用程序中,使用
Task
来执行长时间的文件读取操作,这样在读取文件时,用户界面仍然可以响应用户的其他操作,如点击按钮、移动窗口等。
- 定义:在C#中,
- 创建Task
- 无返回值的Task(
Task
类型)- 使用
Task.Run
方法:Task.Run
是一种简单的创建和启动Task
的方式。它接受一个Action
委托,表示要在另一个线程(通常是从线程池中获取的线程)上执行的操作。例如:
Task.Run(() => { // 这里是要异步执行的代码,例如复杂的计算 for (int i = 0; i < 1000000; i++) { // 一些复杂的数学运算 } });
- 使用
Task.Factory.StartNew
方法:这也是一种创建Task
的方式,和Task.Run
类似,但提供了更多的配置选项。例如:
Task.Factory.StartNew(() => { // 要异步执行的代码 });
- 使用
- 有返回值的Task(
Task<TResult>
类型)- 通过
Task.Run
返回结果:如果异步操作有返回值,可以使用Task<TResult>
,其中TResult
是返回值的类型。例如:
Task<int> taskWithResult = Task.Run(() => { return 42; // 返回一个整数结果 });
- 使用
Task.FromResult
方法(用于已经有结果的情况):如果已经有了一个结果,并且想把它包装成一个Task<TResult>
,可以使用Task.FromResult
。例如:
int resultValue = 10; Task<int> preCompletedTask = Task.FromResult(resultValue);
- 通过
- 无返回值的Task(
- 等待Task完成(
await
和Wait
)await
关键字(在异步方法中使用):await
只能在标记为async
的方法内部使用。当遇到await
时,当前方法的执行会暂停,直到等待的Task
完成。例如:
public async Task DoSomethingAsync() { Task<int> getDataTask = GetDataAsync(); int result = await getDataTask; // 在这里可以使用result,此时getDataTask已经完成 }
Wait
方法(同步等待):如果不想使用异步方式等待Task
完成,可以使用Task
的Wait
方法。但是要注意,使用Wait
会阻塞当前线程。例如:
Task<int> task = Task.Run(() => { return 10; }); task.Wait(); int result = task.Result;
- 获取Task的结果
- 对于
Task<TResult>
类型:可以使用await
(在异步方法中)或者Result
属性(同步方式,但会阻塞)来获取结果。例如: - 使用
await
(异步方式)public async Task<int> GetDataAsync() { Task<int> getDataTask = Task.Run(() => { return 42; }); int result = await getDataTask; return result; }
- 使用
Result
属性(同步阻塞方式)Task<int> task = Task.Run(() => { return 10; }); int result = task.Result;
- 对于
Task
类型(无返回值):主要关注其完成状态,可以通过IsCompleted
、IsFaulted
和IsCanceled
属性来判断。例如:
Task task = Task.Run(() => { // 执行一些操作 }); while (!task.IsCompleted) { // 可以在这里做一些其他事情,等待任务完成 }
- 对于
- 处理Task中的异常
- 在
await
语句中自动传播异常:如果在await
的Task
中出现异常,异常会自动在调用await
的方法中抛出。例如:
public async Task DoSomethingAsync() { try { Task<int> getDataTask = GetDataAsync(); int result = await getDataTask; } catch (Exception ex) { // 在这里处理异常,ex是从getDataTask中抛出的异常 } }
- 使用
Task
的Exception
属性(同步方式):如果是通过Wait
等同步方式等待Task
,可以检查Task
的Exception
属性来获取异常信息。例如:
Task task = Task.Run(() => { throw new Exception("An error occurred"); }); try { task.Wait(); } catch { if (task.Exception!= null) { // 处理异常,task.Exception包含了抛出的异常 } }
- 在
- 组合多个Task(
Task.WhenAll
和Task.WhenAny
)Task.WhenAll
:用于同时等待多个Task
完成。它返回一个新的Task
,当所有传入的Task
都完成时,这个新的Task
才完成。例如:
Task<int> task1 = Task.Run(() => { return 1; }); Task<int> task2 = Task.Run(() => { return 2; }); Task<int[]> allTasks = Task.WhenAll(task1, task2); int[] results = await allTasks; // results[0]是task1的结果,results[1]是task2的结果
Task.WhenAny
:用于等待多个Task
中的任意一个完成。它返回一个新的Task
,当传入的Task
中有一个完成时,这个新的Task
就完成。例如:
Task<int> taskA = Task.Run(() => { System.Threading.Thread.Sleep(2000); return 1; }); Task<int> taskB = Task.Run(() => { System.Threading.Thread.Sleep(1000); return 2; }); Task<Task<int>> anyTask = Task.WhenAny(taskA, taskB); Task<int> completedTask = await anyTask; int result = await completedTask; // result是先完成的task(这里是taskB)的结果
C# Task的详细使用说明
最新推荐文章于 2025-03-21 13:42:49 发布