应无所住,而生其心
排名
1
文章
860
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

注意async task返回 void 对象被释放问题

2185人阅读 2021/6/23 13:23 总访问:5182362 评论:0 收藏:0 手机
分类: .NET

异步方法要尽量避免使用void返回值,就是不要写成async void这种写法,就算不要返回值也要写成async task。因为一旦使用了async void这种写法,方法就不能被等待了,调用这个方法的地方就不会去等待这个方法的执行,就容易造成各种对象被释放的问题,常见的就是ef上下文对象在异步情况下被自动释放的问题。

C#的异步方法可以定义三种返回方式: voidTaskTask<TResult> 。其中, Task<TResult> 表示返回一个泛型任务,它可以在完成后提供一个T类型的结果值; Task 表示返回一个非泛型任务,它只表示一个异步操作的状态; void 表示不返回任何任务,也就是说,这个异步方法不能被调用者用类似”await”的关键字等待。

void类型的异步方法

  1. /// <summary>
  2. /// void类型的异步方法
  3. /// </summary>
  4. public async void AddInquiryAndLoadPortAsync()
  5. {
  6. await DoAddInquiry();
  7. }

返回void的async方法不能被等待。这种方法只适用于异步事件处理器或其他不需要等待或错误处理的场景。返回void的async方法不能被等待,是因为它不返回任何对象,也就是说,它没有任何可被等待的任务。在C#中,要想一个对象能被等待,它必须有一个名为GetAwaiter的实例方法或扩展方法,这个方法可以返回一个awaiter对象,用于表示异步操作的状态和结果。而返回void的async方法不会产生任何对象,所以它没有GetAwaiter方法,也没有awaiter对象。因此,如果我们试图使用await关键字来等待一个返回void的async方法,编译器就会报错。这种方式又叫”发起并遗忘(Fire-and-forget)”,只管发起调用,不管后续的执行状态和结果。

异步方法要尽量避免使用void返回值,调用这个方法的地方就不会去等待这个方法的执行,就容易造成各种对象被释放的问题,常见的就是ef上下文对象在异步情况下被自动释放的问题。

返回Task的异步方法

  1. /// <summary>
  2. /// 返回Task的异步方法
  3. /// </summary>
  4. /// <returns></returns>
  5. public async Task AddInquiryAndLoadPortAsync()
  6. {
  7. await DoAddInquiry();
  8. }

返回TaskTask<TResult>的async方法可以被等待。它适用于大多数异步编程的场景,可以让调用方跟踪任务的执行状态。

这种方式也叫”等待并继续(Wait-and-continue)”,发起调用后还继续跟踪任务的执行状态和结果。

返回Task TResult的异步方法

  1. /// <summary>
  2. /// 返回Task<TResult>的异步方法
  3. /// </summary>
  4. /// <returns></returns>
  5. public async Task<bool> AddInquiryAndLoadPortAsync()
  6. {
  7. bool isAdd = await DoAddInquiry();
  8. return isAdd;
  9. }
  10. // 随便模拟一个异步方法
  11. public Task<bool> DoAddInquiry()
  12. {
  13. return Task.Run<bool>(() =>
  14. {
  15. return true;
  16. });
  17. }

和上面的方法原理一样,方法可以被等待,还可以在调用方通过Task<TResult>获得执行结果。能获取到方法的状态也能获取到方法的结果。

相关原理解释

异步方法会被编译为一个状态机,状态机根据 await 将异步方法划分为若干片段,每执行完一个片段,就切出状态机,等待调度器重新调度。await 的原理就是调用 GetAwaiter() 方法获取 Awaiter 对象,状态机从而决定下一步动作。而 Awaiter 对象是从 Task 对象中获取的。如果异步方法的返回值是 void,也就意味着外部调用者无法获取 Awaiter 对象,其最严重的后果是,外部调用者无法捕获异步任务的异常。那么一旦异步任务发生异常,除非自行处理掉,否则该异常会直接沿着后台工作线程的调用堆栈直接传播到当前应用程序域 AppDomain,从而引发进程异常,导致整个进程崩溃。所以,在实践中,异步方法尽量少用 void。不是说彻底禁止返回值为 void 的异步方法,而是要明白其工作原理。返回值为 void 的异步方法的最常见使用场景是异步事件。但需要注意的是,由于外部调用者捕获不到异步事件里的异常,所以异步事件本身必须要通过 try-catch 处理掉自身的异常。


欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价

nginx配置负载均衡注意事项

一.如果location下面的proxy_pass配置有端口号nginx就会直接反向代理到这个地址这样你配置的upstream就没有用了,即使名字和...

Redis集群注意事项

当主节点运行起,并且有项目在运行与其他子节点运行中,这个时候如果在添加子节点,这个时候可能会造成redis的死锁,一直访...

nginx配置注意事项

一.要注意后面要加一个分号:不然就会报这个错:

WebApi中间件框架注意事项

在写调用WebApi接口的中间件框架时,有些类型错误,需要记录一下。像这种code返回成功!出参却没有数据,错误原因有几种情...

东途网:新手如何运营抖音?最全运营技巧、注意事项来啦!

东途网:www.dtwl.top新手如何运营抖音?最全运营技巧、注意事项来啦!抖音是目前最火爆的短视频,越来越多的人都离不开短视...

一个使用refs需要注意的问题

一、问题的提出 在vue文件中给一个组件设置了ref属性,目的是后续代码中能够触发该组件上的一些自带方法:&lt;q-uploader ...

Xamarin 开发环境注意事项

Xamarin 开发环境注意事项[TOC] 配置Android SDK创建一个Blank的Xamarin项目,打开Open Android SDK Manager管理,添加7.0...

sqlsugar 对接mysql分表。sqlsguar分表注意事项。分表思路,通过日期获取分表表名等

官方文档:https://www.donet5.com/Home/Doc?typeId=1201 sqlsguar分表注意事项注意一:需要有一个分表字段,插入的时候...

vs2017 对 COM 组件的调用返回了错误 HRESULT E_FAIL

vs2017添加引用报错 对 COM 组件的调用返回了错误 HRESULT E_FAIL 1.以管理员身份打开vs2017开发人员命令指示符 2...

实现返回顶部效果

实现返回顶部效果2:http://www.tnblog.net/aojiancc2/article/details/2677实现的效果如下可以点击它返回到首页去html部分...

远程服务器返回错误: (403) 已禁止。

今天调用接口的时候报的错。我们只要加上这两句代码就行了呢HttpWebRequestreq=(HttpWebRequest)HttpWebRequest.Create(url...

扩展ef自动映射需要查询的字段(表达式树Expression),动态构建返回

Entity Framework 动态构造select表达式比如我们需要返回某些字段会采用如下的写法但是发现每次都去写select如果字段很多不...

实现返回顶部效果2

实现返回顶部效果1:http://www.tnblog.net/aojiancc2/article/details/164效果如下:html:&lt;divclass=&quot;rollto&quot...

.net webapi Newtonsoft.Json返回需要的字段,忽略某些字段,修改字段名,动态返回需要的字段等

有时候我们在写webapi的时候,不想把正常用的对象所有字段都返回,我们需要进行一些筛选,忽略某些字段,大概说一下几种方法...

.net webapi 返回json格式

.net framework中webapi默认返回的是xml格式,想要返回json格式可以如下操作。方法一:使用HttpResponseMessage单个返回jso...