首页 > 编程语言 >C# Async异步

C# Async异步

时间:2023-05-19 16:33:40浏览次数:48  
标签:异步 Task Console C# task result WriteLine Async

原文链接:https://blog.csdn.net/zuheyawen/article/details/99863588

转载连接:https://www.cnblogs.com/wcrBlog/p/11690460.html

前言

C#异步编程有几种实现方式,异步方法就是其中的一种。异步方法是 C#5.0 才有的新特性,主要采用 async、await 关键字声明为异步方法,完成对方法的异步调用。C#5.0 对应的 VS 版本是 VS2012,对应的 .NET Framework 版本是 v4.5,所以需要在此基础上才支持。(否则可能报:找不到“async”修饰符所需的所有类型。目标框架版本是否不正确,或者缺少对程序集的引用?)

什么是异步方法
1. 异步方法,是指在执行当前方法的同时,可以异步的去调用其他方法(异步方法),并且不会阻塞当前方法的线程。
2. 使用了 async 修饰符的方法称为异步方法,通常配合 await 运算符和 Task 异步任务一起使用。
1) 如果方法使用了 async 修饰符,则方法中需要包含一个以上 await 运算符,否则将以同步执行。
2) 反之,如果方法中包含一个以上 await 运算符,则必须声明为一个异步方法,即使用 async 修饰符。

3. Task 分为两种:
1) Task,表示可以执行一个异步操作,声明如下:
public class Task : IAsyncResult, IDisposable { }
2) Task<TResult>,表示可以执行带有返回值的异步操作,声明如下:
public class Task<TResult> : Task { }

4. 异步方法的返回类型必须为 void、Task、Task<TResult> 中的其中一种。
1) void,表示无返回值,不关心异步方法执行后的结果,一般用于仅仅执行某一项任务,但是不关心结果的场景。
2) Task,表示异步方法将返回一个 Task 对象,该对象通常用于判断异步任务是否已经完成,可以使用 taskObj.Wait() 方法等待,或者 taskObj.IsCompleted 判断。
3) Task<TResult>,表示异步方法将返回一个 Task<TResult> 对象,该对象的 Result 属性则是异步方法的执行结果,调用该属性时将阻塞当前线程(异步方法未执行完成时)。

归纳一下:void 不关心结果;Task 只关心是否执行完成;Task<TResult> 不止关心是否执行完成,还要获取执行结果。

下面通过几个生活中比较形象的例子来理解异步方法的使用

 

// See https://aka.ms/new-console-template for more information


//Async.DropLitter();

//Async.OpenMainsSwitch();

//Async.CookDinner();

//Async.AsyncBuyGoods();

//Async.CookDinner_CancelBuySalt();

Async.CookDinner_MultiCancelBuySalt();
public static class Async
{
#region 扔垃圾为例 不关心结果, 返回void类型
/// <summary>
/// 扔垃圾
/// </summary>
public static void DropLitter()
{
Console.WriteLine("老婆开始打扫房间");
Console.WriteLine("垃圾满了,快起扔垃圾");
CommandDropLitter();
Console.WriteLine("不管他继续打扫");
Thread.Sleep(1000);
Console.WriteLine("老婆把房间打扫好了");
}

/// <summary>
/// 通知我去扔垃圾
/// </summary>
public static async void CommandDropLitter()
{
Console.WriteLine("这时我准备去扔垃圾");
await Task.Run(() =>
{
Console.WriteLine("屁颠屁颠去扔垃圾");
Thread.Sleep(1000);
});
Console.WriteLine("垃圾扔了还有啥吩咐");
}
#endregion


#region 看电视为例 关心是否执行完成,返回Task类型

public static void OpenMainsSwitch()
{
Console.WriteLine("我和老婆正在看电视");
Console.WriteLine("突然停电,快去看下是不是跳闸了");
Task task = CommandOpenMainSwitch();
Console.WriteLine("没电了先玩会手机吧");
//Thread.Sleep(100);
Console.WriteLine("手机也没电了只能等电源打开");

while (!task.IsCompleted) { Thread.Sleep(100); }

Console.WriteLine("又有电了我们继续看电视");
}

public static async Task CommandOpenMainSwitch()
{
Console.WriteLine("这时我准备去打开电源开关");
await Task.Run(() => {
Console.WriteLine("屁颠屁颠的去打开电源开关");
//Thread.Sleep(1000);
});

Console.WriteLine("电源开关打开了");
}
#endregion


#region 买盐 不止关心是否执行完成,还要获取执行结果。返回 Task<TResult> 类型
public static void CookDinner()
{
Console.WriteLine("老婆开始做饭");
Console.WriteLine("哎呀,没盐了");
Task<string> task = CommandBuySalt();
Console.WriteLine("不管他继续炒菜");
//Thread.Sleep(100);
string result = task.Result;
Console.WriteLine("用了盐炒的菜就是好吃【{0}】", result);
Console.WriteLine("老婆把饭做好了");
}

public static async Task<string> CommandBuySalt()
{
Console.WriteLine("这时我准备去买盐了");
string result = await Task.Run(() =>
{
Console.WriteLine("屁颠屁颠的去买盐");
//Thread.Sleep(1000);
return "盐买回来了,顺便我还买了一包烟";
});
Console.WriteLine(result);
return result;
}
#endregion

#region 买盐买烟买酒 异步方法中开启多个Task

public static void AsyncBuyGoods()
{
Console.WriteLine("老婆开始做饭");
Console.WriteLine("哎呀,没盐了");
Task task = BuyGoods();
Console.WriteLine("不管他继续炒菜");
task.Wait();
Console.WriteLine("老婆把饭做好了");
Console.WriteLine("抽着烟,喝着酒,吃着用了盐炒的菜,生活乐无边");
}

public static async Task BuyGoods()
{
Console.WriteLine("这时我准备去买盐了");
await Task.Factory.StartNew((state) =>
{
Console.WriteLine("先买了包盐{0}", state);

Console.WriteLine("顺便买了包烟{0}", state);
}, "task1");

await Task.Factory.StartNew((state) =>
{
Console.WriteLine("有菜没酒,快乐减半{0}", state);

Console.WriteLine("再去买瓶酒{0}", state);
}, "task2");
Console.WriteLine("买完东西,回家了");
}
#endregion

#region 买盐为例 取消异步

public static void CookDinner_CancelBuySalt()
{
Console.WriteLine("老婆开始做饭");
Console.WriteLine("哎呀,没盐了");
CancellationTokenSource source = new CancellationTokenSource();
Task<string> task = CommandBuySalt_CancelBuySalt(source.Token);
Console.WriteLine("不管他继续炒菜");
Thread.Sleep(100);
string result = "家里的盐";
if (!string.IsNullOrEmpty(result))
{
source.Cancel(); //传达取消请求
Console.WriteLine("家里有盐不用买了");
}
else
{
result = task.Result;
}
Console.WriteLine("既然有盐我就继续炒菜{0}", result);
Console.WriteLine("老婆把菜做好了");
Console.WriteLine("任务的状态:{0},已完成:{1},已取消:{2},已失败{3}",
task.Status, task.IsCanceled, task.IsCanceled, task.IsFaulted);
}

public static async Task<string> CommandBuySalt_CancelBuySalt(CancellationToken token)
{
Console.WriteLine("我准备出去买盐");

//已开始执行的任务不能被取消
string result = await Task.Run(() =>
{
Console.WriteLine("屁颠屁颠的去买盐");
Thread.Sleep(1000);
}, token).ContinueWith((t) => //若没有取消就继续执行
{
Console.WriteLine("盐已经买好了");
Thread.Sleep(1000);
return "盐买回来了,顺便我还买了一包烟";
}, token);
Console.WriteLine("{0}", result);
return result;
}

#endregion

#region 买盐为例 多个 CancellationTokenSource 取消异步任务,以及注册取消后的回调委托方法

public static void CookDinner_MultiCancelBuySalt()
{
Console.WriteLine("老婆开始做饭");
Console.WriteLine("哎呀,没盐了");
CancellationTokenSource source1 = new CancellationTokenSource();
CancellationTokenSource source2 = new CancellationTokenSource();
CancellationTokenSource source = CancellationTokenSource.CreateLinkedTokenSource(source1.Token, source2.Token);

//注册取消时的回调委托
source1.Token.Register(() =>
{
Console.WriteLine("因为{0}所以取消", "家里有盐");
});

source2.Token.Register((state) =>
{
Console.WriteLine("因为{0},所以取消", state);
},"不做了出去吃");
source.Token.Register((state) =>
{
Console.WriteLine("因为{0}所以取消", state);
},"没理由");

//这里必须传递 CancellationTokenSource.CreateLinkedTokenSour1e() 方法返回的 Token 对象
Task<string> task = CommandBuySalt_MultiCancelBuySalt(source.Token);

Console.WriteLine("等等,好像不用买了");
Thread.Sleep(100);

string[] result = new string[] { "家里的盐", "不做了出去吃", "没理由" };
Random r = new Random();
switch (r.Next(1,4))
{
case 1:
source1.Cancel(); //传达取消请求(家里有盐)
//source1.CancelAfter(3000); //3s后才调用取消的回调方法
Console.WriteLine("既然有盐我就继续炒菜{0}", result[0]);
break;
case 2:
source2.Cancel(); //传达取消请求(不做了出去吃)
//source2.CancelAfter(3000); //3s后才调用取消的回调方法
Console.WriteLine("我们出去吃不用买啦{0}", result[1]);
break;
case 3:
source.Cancel();
Console.WriteLine("没理由就是不用买啦{0}", result[2]);
break;
default:
break;
}
Console.WriteLine("最终的任务状态是:{0},已完成{1},已取消{2},已失败{3}",
task.Status,task.IsCanceled,task.IsCanceled,task.IsFaulted);
}

/// <summary>
/// 通知我去买盐(又告诉我不用买了,各种理由)
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public static async Task<string> CommandBuySalt_MultiCancelBuySalt(CancellationToken token)
{
Console.WriteLine("这时我准备去买盐了");
//已开始执行的任务不能被取消
string result = await Task.Run(() =>
{
Console.WriteLine("屁颠屁颠的去买盐");
Thread.Sleep(1000);
}, token).ContinueWith((t) => //若没有取消就继续执行
{
Console.WriteLine("盐已经买好了");
Thread.Sleep(1000);
return "盐买回来了,顺便我还买了一包烟";
},token);
Console.WriteLine("{0}",result);
return result;
}

 

#endregion
}

 

标签:异步,Task,Console,C#,task,result,WriteLine,Async
From: https://www.cnblogs.com/KevinSteven/p/17415556.html

相关文章

  • closeSocket:fail task not found, uniapp 微信小程序连接不上mqtt!!!
    原来使用的mqttjs版本为4.3.7,连接一直报错,closeSocket:failtasknotfound。降低mqtt.js版本使用4.1.0。引入mqtt的方式使用importmqttfrom'mqtt/dist/mqtt.js'!!!使用constmqtt=require('mqtt'),require方式也提示无法连接!!!......
  • docker从入门到实践学习笔记【环境ubuntu16.04】【一】
    镜像加速国内从DockerHub拉取镜像有时会遇到困难,此时可以配置镜像加速器。Docker官方和国内很多云服务商都提供了国内加速器服务,例如: Docker官方提供的中国registrymirrorhttps://registry.docker-cn.com七牛云加速器https://reg-mirror.qiniu.com/ 我们以Docker官......
  • docker从入门到实践学习笔记【环境ubuntu16.04】【二】
     目录获取镜像 运行容器列出镜像虚悬镜像中间层镜像 删除本地镜像批量删除镜像  镜像是docker的三大组件之一。Docker运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker会从镜像仓库下载该镜像。 获取镜像 从Docker镜像仓库获取镜像的命令是dockerpull。......
  • docker从入门到实践学习笔记【环境ubuntu16.04】【三】
    目录 新建容器并启动启动已经终止的容器后台运行终止容器进入容器导入和导出容器导出容器导入容器删除容器清理所有终止状态的容器新建容器并启动 dockerrun 例如,下面的命令输出一个“HelloWorld”,之后终止容器 $dockerrunubuntu:14.04/bin/echo'Helloworld'Hellow......
  • docker从入门到实践学习笔记【环境ubuntu16.04】【四】
    目录数据卷创建一个数据卷查看所有数据卷查看指定数据卷的详细信息启动容器的同时挂在数据卷查看容器的信息删除数据卷在容器销毁时自动删除数据卷挂载主机目录作为数据卷挂载一个本地主机文件作为数据卷  数据卷数据卷特性:1.可以在容器之间共享和重用2.对数据卷的修改立马生效3.......
  • yum安装gcc时降级安装包的问题
    安装gccgcc-c++make等编译包,提示glibc错误依赖-->FinishedDependencyResolutionError:Package:glibc-headers-2.17-317.el7.x86_64(centos7)Requires:glibc=2.17-317.el7Installed:glibc-2.17-326.el7_9.x86_64(@anaconda)......
  • 更高效便捷的开发体验——Cloud Studio 编辑器命令行工具
    CloudStudio是一个云端在线开发平台,在CloudStudio的控制台页面中,可以方便快捷创建或者打开一个工作空间。工作空间提供了在线编辑器给大家访问远端开发环境。大部分开发时间都与这个在线编辑器打交道,在线编辑器效果如下图所示:通过该在线编辑器,可以使用编辑器UI进行如下操......
  • C# 集合
    简介集合表示一组具有某种性质的数学元素,引用到程序设计中表示一组具有相同性质的对象。集合的大小可以动态调整,也可以在运行时添加或删除元素官方文档System.Collections数组集合泛型集合Concurrent线程安全集合System.Collections.Specialized集合基类接口ICollect......
  • 虚拟化技术 - CPU虚拟化
    本文分享自天翼云开发者社区《虚拟化技术 -CPU虚拟化》,作者:谢****悦 物理机器是由CPU,内存和I/O设备等一组资源构成的实体。虚拟机也一样,由虚拟CPU,虚拟内存和虚拟I/O设备等组成。VMM(VMMonitor)按照与传统OS并发执行用户进程的相似方式,仲裁对所有共享资源的访问。本文将分别......
  • svn Ignore for Visual Studio C#
    *.o*.lo*.la*.al.libs*.so*.so.[0-9]**.a*.pyc*.pyo*.rej*~#*#.#*.*.swp.DS_Store.vs*/bin*/obj*/Release*/Debug*.suo*.err*.log*.obj*.bin*.LOG*.user*.pdb[tT]emp[tT]empPEAnkh.Loadthumbs.db*.resharper*.vspscc*.vsssccc*.scc*/_Re......