C# Task 包含 await ConfigureAwait CancellationTokenSource

本文主要是介绍C# Task 包含 await ConfigureAwait CancellationTokenSource,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • `Task`
    • 以下是 `Task` 类的一些关键特性和用法:
    • 以下是一些使用 `Task` 的示例:
    • 创建并启动一个任务
    • 使用 `await` 等待任务完成
    • 处理任务异常
    • 使用 `Task<TResult>` 获取结果
    • 取消任务
    • 总结
  • `await`
      • 暂停方法执行:
      • 非阻塞调用:
      • 任务结果获取:
      • 异常处理:
      • 同步上下文恢复:
      • 配置任务继续执行的线程:
      • 组合异步操作:
      • 简化异步编程:
    • 下面是一个使用 `await` 的简单示例:
  • `ConfigureAwait`
    • 使用场景
    • 语法
    • 参数
    • 示例
    • 总结
  • `CancellationTokenSource`
    • 下面是一个使用 `CancellationTokenSource` 的示例:
    • 总结
  • 个人理解
    • 例子如下
    • 运行结果如下

Task

C#中,TaskSystem.Threading.Tasks 命名空间中的一个类,它代表了异步操作 的执行。Task 类是异步编程模型的核心,它允许开发者编写非阻塞的代码,提高应用程序的响应性和性能。

以下是 Task 类的一些关键特性和用法:

  • 表示异步操作:Task 表示一个可能已经完成、正在运行或尚未开始的异步操作。

  • 返回值:Task<TResult>Task 的泛型版本,它表示一个异步操作,该操作将返回一个指定类型的结果。

  • 状态跟踪:Task 对象提供了属性来跟踪其状态,如 StatusIsCompletedIsFaulted 等。

  • 异常处理:如果异步操作中发生异常,Task 对象的 Exception 属性将包含异常信息。

  • 等待完成:可以使用 await 关键字或 Task.Wait()Task.Result 方法来等待 Task 完成。

  • 取消支持:Task 支持使用 CancellationToken 来取消操作。

  • 连续性:可以使用 ContinueWith 方法来安排在任务完成后执行的连续任务。

  • 并行执行:Task 可以与其他任务并行执行,使用 Task.WhenAllTask.WhenAny 来管理多个任务的完成。

以下是一些使用 Task 的示例:

创建并启动一个任务

// 创建并启动一个任务
Task task = Task.Run(() => 
{Console.WriteLine("Task is running on thread: " + Thread.CurrentThread.ManagedThreadId);
});
// 等待任务完成
task.Wait();

使用 await 等待任务完成

public async Task DoWorkAsync()
{await Task.Run(() => {// 模拟长时间运行的任务Thread.Sleep(1000);Console.WriteLine("Work is done.");});
}

处理任务异常

public async Task DoWorkWithExceptionAsync()
{try{await Task.Run(() => {throw new InvalidOperationException("Something went wrong!");});}catch (Exception ex){Console.WriteLine($"Caught an exception: {ex.Message}");}
}

使用 Task<TResult> 获取结果

public async Task<int> GetResultAsync()
{return await Task.Run(() => {// 模拟计算过程return 42;});
}

取消任务

public async Task CancelTaskAsync(CancellationToken cancellationToken)
{var task = Task.Run(() =>{while (!cancellationToken.IsCancellationRequested){// 模拟长时间运行的任务}}, cancellationToken);await Task.Delay(100); // 模拟一段时间后取消任务cancellationToken.Cancel();await task;
}

总结

Task 类是.NET异步编程的基础,它提供了一种简单而强大的方式来编写和组织异步代码。


await

C# 中,await 关键字用于异步编程,它有几个关键作用

暂停方法执行:

当编译器遇到一个 await 表达式时,它会暂停当前 async 方法的执行,直到被 await 的任务(TaskTask<T>)完成。

非阻塞调用:

await 允许程序在等待异步操作完成时继续执行其他代码。这意味着程序可以执行其他任务,而不是被阻塞等待异步操作的完成。

任务结果获取:

await 一个 Task<T> 时,它返回任务的结果。一旦任务完成,await 表达式的结果就是 Task<T> 的结果。

异常处理:

如果 await 的任务失败并抛出异常,异常会被传播到 await 调用的地方。如果 await 被包含在一个 try 块中,异常可以被捕获和处理。

同步上下文恢复:

await 表达式可以配置为在特定的同步上下文中继续执行(例如,UI 线程)。如果 await 表达式没有指定继续执行的上下文,它将恢复到调用它的原始上下文。

配置任务继续执行的线程:

使用 await 时,可以指定一个 TaskScheduler,来决定任务完成后在哪个线程上继续执行。

组合异步操作:

await 可以与 async 一起使用,创建更复杂的异步工作流,如链式调用多个异步方法。

简化异步编程:

使用 awaitasync 可以大大简化异步代码的编写,使异步代码看起来和同步代码类似,更容易理解和维护。

下面是一个使用 await 的简单示例:

using System;
using System.Threading.Tasks;class Program
{static async Task Main(){int result = await GetNumberAfterDelayAsync();Console.WriteLine(result);}static async Task<int> GetNumberAfterDelayAsync(){await Task.Delay(1000); // 模拟异步操作,延迟1秒return 42; // 返回结果}
}

在这个示例中,Main 方法使用 await 等待 GetNumberAfterDelayAsync 方法完成,并获取它返回的整数结果。await 使得 Main 方法可以非阻塞地等待异步操作的完成。


ConfigureAwait

C#中,ConfigureAwait 是一个方法,用于配置 await 操作是否继续在原始的同步上下文上执行,或者是否继续在不同的上下文上执行。这通常在异步编程中使用,特别是在使用 Taskasync 关键字时。

当你调用一个异步方法并使用 await 时,await 会返回一个 TaskTask<T> 对象。ConfigureAwaitTask 的一个扩展方法,允许你指定是否要捕获当前的同步上下文,并在继续执行异步操作时使用它。

使用场景

通常,当你在 UI 应用程序中使用异步方法时,你可能希望在 UI 线程上继续执行,以更新 UI 元素。默认情况下,await 会尝试捕获当前的同步上下文,并在异步操作完成后返回到这个上下文。但是,如果你在一个没有 UI 线程的上下文中使用 await,或者你希望避免不必要的上下文捕获,你可以使用 ConfigureAwait(false)

语法

await someTask.ConfigureAwait(false);

参数

false:指示 await 操作不需要捕获当前的同步上下文。这意味着当异步操作完成时,它不会尝试返回到原始的上下文,这可以提高性能,尤其是在没有 UI 线程或不需要 UI 更新的情况下。

true默认值):指示 await 操作应该捕获当前的同步上下文,并在异步操作完成后返回到这个上下文。这在需要更新 UI 或访问线程绑定对象时非常有用。

示例

public async Task SomeAsyncMethod()
{// 执行一些异步操作await SomeOtherAsyncMethod().ConfigureAwait(false);// 继续执行其他操作,这里不会捕获原始的同步上下文
}

总结

使用 ConfigureAwait(false) 可以提高性能,特别是在高并发的环境下,因为它避免了不必要的上下文切换。然而,你应该谨慎使用它,确保不会因此而违反线程安全或 UI 更新的需求


CancellationTokenSource

CancellationTokenSourceC#中的一个类,它提供了一种机制来发出取消请求。这个类与 CancellationToken 类一起使用,允许异步操作被取消。以下是 CancellationTokenSource 的一些关键特性和用法:

  • 创建: 你可以创建一个 CancellationTokenSource 的实例来开始一个取消操作。

  • 取消: 通过调用 CancellationTokenSourceCancel 方法,你可以发出取消请求。

  • 传播取消: CancellationTokenSource 可以传播取消请求到所有与之关联的 CancellationToken 对象。

  • 超时: 你可以设置一个超时时间,如果超时时间到了,取消请求会自动发出。

  • 链接: 你可以将多个 CancellationTokenSource 实例链接在一起,这样任何一个源发出取消请求,都会传播到所有链接的源。

下面是一个使用 CancellationTokenSource 的示例:

using System;
using System.Threading;
using System.Threading.Tasks;public class Program {public static void Main() {// 创建CancellationTokenSourcevar cts = new CancellationTokenSource();// 创建CancellationTokenCancellationToken token = cts.Token;// 启动一个异步任务Task task = Task.Run(() =>DoLongRunningOperation(token), token);// 模拟用户决定取消操作Console.WriteLine("按任意键取消操作...");Console.ReadKey();// 发出取消请求cts.Cancel();try {// 等待任务完成或抛出异常task.Wait();} catch (AggregateException ae) {// 处理取消异常foreach (var e in ae.InnerExceptions) {if (e is OperationCanceledException) {Console.WriteLine("操作已被取消。");}}}}private static void DoLongRunningOperation(CancellationToken cancellationToken) {for (int i = 0; i < 10; i++) {// 检查是否有取消请求cancellationToken.ThrowIfCancellationRequested();// 模拟长时间的工作Thread.Sleep(1000);Console.WriteLine($"执行步骤 {i + 1}");}}
}

总结

在这个示例中,我们创建了一个 CancellationTokenSource 并从它获取了一个 CancellationToken。然后,我们启动了一个异步任务 DoLongRunningOperation,并将 CancellationToken 传递给它。当用户按下任意键时,我们调用 Cancel 方法来发出取消请求。如果任务被取消,DoLongRunningOperation 方法中的 ThrowIfCancellationRequested 将抛出 OperationCanceledException 异常,我们捕获这个异常并处理它。


个人理解

对于一个aysnc修饰的方法,没有什么特殊的,调用也是正常的按顺序执行,但是,一旦你使用了await
就会出现这样的事情:

  • 首先,由于必须在有aysnc修饰的方法中使用await
  • 于是就说明的async的作用——将方法包装成状态机,
  • 所以在执行到await时:对于主线程来说,整个状态机(async修饰的方法)都会被挂起,然后这个方法会到其他线程执行,主线程继续执行该方法之后的语句,直到await后面的语句执行完毕,
  • 最后方法从被挂起的状态回归

例子如下

using System;
using System.Threading;
using System.Threading.Tasks;public class Program {public async static Task Main() {var cts = new CancellationTokenSource();CancellationToken token = cts.Token;try {DoLongRunningOperation(token);Console.WriteLine("Main  Thread:" + Environment.CurrentManagedThreadId);Thread.Sleep(500);cts.Cancel();} catch (TaskCanceledException ee) {Console.WriteLine(ee.Message);}Console.ReadKey();}private async static Task DoLongRunningOperation(CancellationToken cancellationToken) {int i = 1;while (!cancellationToken.IsCancellationRequested) {Console.WriteLine("DoLo  Thread:" + Environment.CurrentManagedThreadId);await Task.Delay(100);Console.WriteLine($"{i++}");}}
}

运行结果如下

DoLo  Thread:1
Main  Thread:1
1
DoLo  Thread:4
2
DoLo  Thread:4
3
DoLo  Thread:4
4
DoLo  Thread:4
5

这篇关于C# Task 包含 await ConfigureAwait CancellationTokenSource的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1059495

相关文章

2. c#从不同cs的文件调用函数

1.文件目录如下: 2. Program.cs文件的主函数如下 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace datasAnalysis{internal static

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

C# dateTimePicker 显示年月日,时分秒

dateTimePicker默认只显示日期,如果需要显示年月日,时分秒,只需要以下两步: 1.dateTimePicker1.Format = DateTimePickerFormat.Time 2.dateTimePicker1.CustomFormat = yyyy-MM-dd HH:mm:ss Tips:  a. dateTimePicker1.ShowUpDown = t

C#关闭指定时间段的Excel进程的方法

private DateTime beforeTime;            //Excel启动之前时间          private DateTime afterTime;               //Excel启动之后时间          //举例          beforeTime = DateTime.Now;          Excel.Applicat

C# 防止按钮botton重复“点击”的方法

在使用C#的按钮控件的时候,经常我们想如果出现了多次点击的时候只让其在执行的时候只响应一次。这个时候很多人可能会想到使用Enable=false, 但是实际情况是还是会被多次触发,因为C#采用的是消息队列机制,这个时候我们只需要在Enable = true 之前加一句 Application.DoEvents();就能达到防止重复点击的问题。 private void btnGenerateSh

C# double[] 和Matlab数组MWArray[]转换

C# double[] 转换成MWArray[], 直接赋值就行             MWNumericArray[] ma = new MWNumericArray[4];             double[] dT = new double[] { 0 };             double[] dT1 = new double[] { 0,2 };

C# Hash算法之MD5、SHA

MD5我们用的还是比较多的,一般用来加密存储密码。但是现在很多人觉MD5可能不太安全了,所以都用上了SHA256等来做加密(虽然我觉得都差不多,MD5还是能玩)。 还是跟上一篇说的一样,当一个算法的复杂度提高的同时肯定会带来效率的降低,所以SHA和MD5比较起来的话,SHA更安全,MD5更高效。 由于HASH算法的不可逆性,所以我认为MD5和SHA主要还是应用在字符串的"加密"上。 由于

C#线程系列(1):BeginInvoke和EndInvoke方法

一、线程概述 在操作系统中一个进程至少要包含一个线程,然后,在某些时候需要在同一个进程中同时执行多项任务,或是为了提供程序的性能,将要执行的任务分解成多个子任务执行。这就需要在同一个进程中开启多个线程。我们使用 C# 编写一个应用程序(控制台或桌面程序都可以),然后运行这个程序,并打开 windows 任务管理器,这时我们就会看到这个应用程序中所含有的线程数,如下图所示。

C#设计模式(1)——单例模式(讲解非常清楚)

一、引言 最近在学设计模式的一些内容,主要的参考书籍是《Head First 设计模式》,同时在学习过程中也查看了很多博客园中关于设计模式的一些文章的,在这里记录下我的一些学习笔记,一是为了帮助我更深入地理解设计模式,二同时可以给一些初学设计模式的朋友一些参考。首先我介绍的是设计模式中比较简单的一个模式——单例模式(因为这里只牵涉到一个类) 二、单例模式的介绍 说到单例模式,大家第一