await & async模式是C#中一个很重要的特性,可以用来提高异步程序(多线程程序)的执行效率。但是如果尝试用await关键字来await一个为null的Task对象,会导致程序抛出NullReferenceException异常。

新建一个.NET Core控制台项目,贴入如下代码:

using System;
using System.Threading;
using System.Threading.Tasks; namespace AwaitNull
{
class Program
{
/// <summary>
/// AwaitNullTask方法中的代码会await一个为null的Task t,这样做会抛出NullReferenceException异常
/// </summary>
static async Task AwaitNullTask()
{
Task t = null;//声明一个为null的Task对象t try
{
await t;//await为null的Task对象t,会导致这里抛出NullReferenceException异常 Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : Await finished...");//由于上面抛出了异常,这里的Console.WriteLine不会被执行
}
catch(NullReferenceException e)
{
//输出异常信息
Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : AwaitNullTask threw Exception : {e.GetType().ToString()}");
Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : Exception message : {e.Message}"); throw;//catch后继续抛出NullReferenceException异常到AwaitNullTask方法的外部
}
} static void Main(string[] args)
{
Task taskReturned = AwaitNullTask();//很有意思的是虽然AwaitNullTask方法内部抛出了NullReferenceException异常,但是其并不会影响AwaitNullTask方法外部的方法,就好像AwaitNullTask方法是在另外一个线程上执行的一样,但是本例中我们没有用Task来启动任何线程,可以看到本例中所有Console输出的信息中Thread id都相同,是在同一个线程上 Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : taskReturned status is : {taskReturned.Status.ToString()}");//输出AwaitNullTask方法返回的Task对象taskReturned的Status,由于AwaitNullTask方法内部抛出了异常,所以Task对象taskReturned的Status为Faulted Console.WriteLine();
Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : Press any key to quit...");
Console.ReadKey();
}
}
}

输出结果如下:

我们可以看到AwaitNullTask方法中由于await了一个为null的Task对象,抛出了NullReferenceException异常,但是有意思的是,AwaitNullTask方法表现出的行为是貌似运行在另一个线程上一样,其抛出的NullReferenceException异常并不会影响到Main方法,但实际上Main方法和AwaitNullTask方法都是由同一个线程运行的。

所以我们在使用await关键字等待一个Task或Task<T>对象时,最好加上一个判断逻辑,只有在Task或Task<T>对象不为null时,才进行await。所以我们更改本例中上面的代码如下:

using System;
using System.Threading;
using System.Threading.Tasks; namespace AwaitNull
{
class Program
{
/// <summary>
/// 现在我们在AwaitNullTask方法中加了判断逻辑,只有在Task对象不为null时,才进行await,避免抛出异常
/// </summary>
static async Task AwaitNullTask()
{
Task t = null;//声明一个为null的Task对象t try
{
//判断Task对象t是否为null,不为null才执行下面的await
if (t != null)
{
await t;//因为现在上面的if存在,这里的await就不会被执行了,避免了异常的抛出
Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : Await finished...");
}
}
catch(NullReferenceException e)
{
//输出异常信息
Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : AwaitNullTask threw Exception : {e.GetType().ToString()}");
Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : Exception message : {e.Message}"); throw;//catch后继续抛出NullReferenceException异常到AwaitNullTask方法的外部
} //返回类型为Task的异步方法(使用了async关键字的方法),可以不返回任何值,或者使用return;也可以,.NET会在异步方法结束时自动构造一个Task对象,作为异步方法的返回值
} static void Main(string[] args)
{
Task taskReturned = AwaitNullTask();//这次AwaitNullTask方法没有抛出异常成功返回 Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : taskReturned status is : {taskReturned.Status.ToString()}");//由于AwaitNullTask方法成功返回,所以此时Task对象taskReturned的Status为RanToCompletion,表示AwaitNullTask方法成功执行完毕
//比较有意思的是虽然我们在AwaitNullTask方法中没有return任何东西,但是AwaitNullTask方法还是返回了一个不为null的Task对象taskReturned,并且我们还在上面输出了Task对象taskReturned的Status值,说明.NET为AwaitNullTask方法构造了一个Task对象作为返回值 Console.WriteLine();
Console.WriteLine($"Thread id <{Thread.CurrentThread.ManagedThreadId}> : Press any key to quit...");
Console.ReadKey();
}
}
}

输出结果如下:

所以这次AwaitNullTask方法就不会抛出异常了,成功执行完毕。

C#中如果用await关键字来await一个为null的Task对象会抛出异常的更多相关文章

  1. Async 与 Await 关键字研究

    1        Aynsc 和 Await 关键字的研究 在 .NET 4.0 以后,基于 Task 的异步编程模式大行其道,因其大大简化了异步编程所带来的大量代码工作而深受编程人员的欢迎,如果你曾 ...

  2. C#中的异步编程Async 和 Await

    谈到C#中的异步编程,离不开Async和Await关键字 谈到异步编程,首先我们就要明白到底什么是异步编程. 平时我们的编程一般都是同步编程,所谓同步编程的意思,和我们平时说的同时做几件事情完全不同. ...

  3. .NET中的async和await关键字使用及Task异步调用实例

    其实早在.NET 4.5的时候M$就在.NET中引入了async和await关键字(VB为Async和Await)来简化异步调用的编程模式.我也早就体验过了,现在写一篇日志来记录一下顺便凑日志数量(以 ...

  4. 浅谈async、await关键字 => 深谈async、await关键字

    前言 之前写过有关异步的文章,对这方面一直比较弱,感觉还是不太理解,于是会花点时间去好好学习这一块,我们由浅入深,文中若有叙述不稳妥之处,还请批评指正. 话题 (1)是不是将方法用async关键字标识 ...

  5. 多线线程async与await关键字

    创建线程 //这里面需要注意的是,创建Thread的实例之后,需要手动调用它的Start方法将其启动. //但是对于Task来说,StartNew和Run的同时,既会创建新的线程,并且会立即启动它. ...

  6. WebApi上传图片 await关键字

    await关键字对于方法执行的影响 将上一篇WebApi上传图片中代码修改(使用了await关键字)如下: [HttpPost] public async Task<string> Pos ...

  7. async和await关键字实现异步编程

    async和await关键字实现异步编程 异步编程   概念 异步编程核心为异步操作,该操作一旦启动将在一段时间内完成.所谓异步,关键是实现了两点:(1)正在执行的此操作,不会阻塞原来的线程(2)一旦 ...

  8. 为什么我们要使用Async、Await关键字

    前不久,在工作中由于默认(xihuan)使用Async.Await关键字受到了很多质问,所以由此引发这篇博文“为什么我们要用Async/Await关键字”,请听下面分解: Async/Await关键字 ...

  9. 异步编程Async/await关键字

    异步编程Async \await 关键字在各编程语言中的发展(出现)纪实. 时间 语言版本 2012.08.15 C#5.0(VS2012) 2015.09.13 Python 3.5 2016.03 ...

随机推荐

  1. 再谈javascript函数节流

    之前写过但是不记得在哪了,今天同事要一个滑到页面底部加载更多内容的效果,又想起了这玩意儿,确实挺实用和常用的,谨此记之. 函数节流从字面上的意思就是节约函数的执行次数,其实现的主要思想是通过定时器阻断 ...

  2. css3 伪元素和伪类选择器详解

    转自脚本之家:http://www.jb51.net/css/213779.html 无论是伪类还是伪元素,都属于CSS选择器的范畴.所以它们的定义可以在CSS标准的选择器章节找到.分别是 CSS2. ...

  3. PHP 如何向关联数组指定的 Key 之前插入元素

    PHP 关联数组可以通过三种方式插入新元素: $array[$insert_key] = $insert_value; $array = array_merge($array, $insert_arr ...

  4. Vue.js小案例(2)

    即时搜索 这个例子主要应用了vue.js的自定义过滤器,可以通过Vue.filter()注册一个全局过滤器,具体用法可以参考这里,vue.js也提供了一些内置过滤器. CSS代码: [v-cloak] ...

  5. Python爬虫教程-00-写在前面

    鉴于好多人想学Python爬虫,缺没有简单易学的教程,我将在CSDN和大家分享Python爬虫的学习笔记,不定期更新 基础要求 Python 基础知识 Python 的基础知识,大家可以去菜鸟教程进行 ...

  6. 131.005 Unsupervised Learning - Cluster | 非监督学习 - 聚类

    @(131 - Machine Learning | 机器学习) 零. Goal How Unsupervised Learning fills in that model gap from the ...

  7. 微信小程序开发10-开发流程

    1.Flex布局 Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性.任何一个容器都可以指定为Flex布局. 2.设置容器,用于统一管理容器内项目布局,也就是管 ...

  8. 在小程序中修改上一个页面里data中的数据调用上一个页面的方法

    //获取已经打开的页面的数组 var pages = getCurrentPages(); //获取上一个页面的所有的方法和data中的数据  var lastpage = pages[pages.l ...

  9. matplotlib点线 坐标刻度 3D图绘制(六)

    plot语句中支持除X,Y以外的参数,以字符串形式存在,来控制颜色.线型.点型等要素,语法形式为: plt.plot(X, Y, 'format', ...) 1 点和线的样式 颜色 参数color或 ...

  10. JQuery学习---JQuery基础知识

    JQuery介绍: [官网]http://jquery.com [参考API]http://jquery.cuishifeng.cn/ JQuery的低版本支持IE低版本,JQuery的2版本不太支持 ...