最近用asp.net core webapi实现了一个实时视频流的推送功能,在Asp.net中,这个是通过PushStreamContent来实现的。

基于对asp.net core的知识,随手写了一个(要求控制器继承自Controller基类)

[HttpGet]
public async Task Get()
{var response = HttpContext.Response;response.ContentType = "text/html";response.StatusCode = 200;var stream = HttpContext.Response.Body;while (true){await Task.Delay(1000);var content = DateTime.Now + @"<br>";var data = Encoding.Default.GetBytes(content);await stream.WriteAsync(data, 0, data.Length);await stream.FlushAsync();}
}

使用chrome调试这个接口时,发现它确实行之有效的将当前的时间推送到了浏览器的页面上。

然而,当我进一步的调试它的异常情况时,发现就算将chrome关掉,这个程序却依然在继续运行。从调试器中看到stream的状态为Aborted,已经识别到位终止的流了。

  

并且从VS的调试窗口也能看到异常信息:

  

但下面这两行就是不抛异常:

await stream.WriteAsync(data, 0, data.Length);
await stream.FlushAsync();

单单从接口的实现角度上来看,这个已经不合理了。这是一个很大的坑,功能看上去还是正确的,没有详细调试还看不出来。一个不留神就踩上了。不知道微软为什么要这么设计。

埋怨归埋怨,问题还是要解决的。我查看了下FileStreamResult的源码,发现它是靠HttpContext.RequestAborted来判断客户端是否终止了的。这是一个CancellationToken类型的对象,当客户端连接断开后,它就处于被取消的状态。

知道原因后,就可以知道如何修改我的程序了。

[HttpGet]
public async Task Get()
{var cancel = HttpContext.RequestAborted;var response = HttpContext.Response;response.ContentType = "text/html";response.StatusCode = 200;var stream = HttpContext.Response.Body;while (true){cancel.ThrowIfCancellationRequested();await Task.Delay(1000, cancel);var content = DateTime.Now + @"<br>";var data = Encoding.Default.GetBytes(content);await stream.WriteAsync(data, 0, data.Length, cancel);await stream.FlushAsync(cancel);}
}

再然后就是封装了,我这里将其封装为了一个PushStreamResult,这样就可以在PocoController中使用了。

class MyPushStreamResult :IActionResult
{Func<Stream, CancellationToken, Task> _pushAction;string _contentType;public MyPushStreamResult(Func<Stream, CancellationToken, Task> pushAction, string contentType){_pushAction = pushAction;_contentType = contentType;}public Task ExecuteResultAsync(ActionContext context){var response = context.HttpContext.Response;response.ContentType = _contentType;response.StatusCode = 200;return _pushAction(response.Body, context.HttpContext.RequestAborted);}
}

使用方法如下:

[HttpGet]
public IActionResult Get()
{return new MyPushStreamResult(pushData, "text/html");
}async Task pushData(Stream stream, CancellationToken cancel)
{while (true){if (cancel.IsCancellationRequested)return;await Task.Delay(1000, cancel);var content = DateTime.Now + @"<br>";var data = Encoding.Default.GetBytes(content);await stream.WriteAsync(data, 0, data.Length, cancel);await stream.FlushAsync(cancel);}
}

转载于:https://www.cnblogs.com/TianFang/p/8502770.html

在Asp.net core返回PushStream相关推荐

  1. iactionresult 图片_从显式类型的ASP.NET Core API控制器(不是IActionResult)返回404

    在ASP.NET Core 2.1中使用return null;解决了此问题: public ActionResult Get(int id) { Thing thing = GetThingFrom ...

  2. asp.net core系列 38 WebAPI 返回类型与响应格式--必备

    一.返回类型 ASP.NET Core 提供以下 Web API Action方法返回类型选项,以及说明每种返回类型的最佳适用情况: (1) 固定类型 (2) IActionResult (3) Ac ...

  3. ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)

    要啥自行车,直接看手表 //返回基元类型public string Get(){return "hello world";} //返回复杂类型public Person Get() ...

  4. 客户要求ASP.NET Core API返回特定格式,怎么办?(续2)

    前言 前2次,我们都是假设客户需要返回不同的字符串格式. 但是,有可能客户要求的返回是非本文格式,比如文件流. 怎么办? 思路 前提,当然还是使用同一API接口,不影响现有使用方式. 虽然ASP.NE ...

  5. 客户要求ASP.NET Core API返回特定格式,怎么办?(续)

    前言 上次,我们用 客户就要求API的返回值属性名必须是PascalCase(如UserName),但是这些API需要同时提供给内部系统使用,默认都是CamelCase(如userName). 其实, ...

  6. ASP.Net Core Web API 如何返回 File。

    咨询区 Jan Kruse: 我想在 ASP.Net Web API 中返回 File 文件,我目前的做法是将 Action 返回值设为 HttpResponseMessage,参考代码如下: pub ...

  7. 客户要求ASP.NET Core API返回特定格式,怎么办?

    当ASP.NET Core API提供给到外部系统使用时,在某些情况下,可能需要根据这些外部系统的要求来格式化数据. 比如,客户就要求API的返回值属性名必须是PascalCase(如UserName ...

  8. asp.net core 使用newtonsoft完美序列化WebApi返回的ValueTuple

    由于开发功能的需要,又懒得新建太多的class,所以ValueTuple是个比较好的偷懒方法,但是,由于WebApi需要返回序列化后的json,默认的序列化只能将ValueTuple定义的各个属性序列 ...

  9. ASP.NET Core WebAPI控制器返回类型的最佳选项

    ASP.NET Core WebAPI控制器返回类型的最佳选项 原文:ASP.NET Core WebAPI控制器返回类型的最佳选项 前言 从.NET Core 2.1版开始,到目前为止,控制器操作可 ...

最新文章

  1. [BTS2004]一步一步学习BizTalk2004 CBR(content-based routing)
  2. 这块DIY墨水屏手表火了!外观可盐可甜,无线蓝牙计步闹钟一应俱全 | 开源
  3. 那些计算机界的伟大女性
  4. 肖婧医生直播讲稿整理
  5. docker中centos遇到sudo: command not found
  6. 分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!
  7. 【笑话】骂人的最高境界
  8. Arduino IDE和ArduBlock 的下载安装
  9. 【转载】SQL Server 2008 中新建用户登录并指定该用户的数据库
  10. Java 工程师修炼之道
  11. 用户手册 (V4.0 版)
  12. 如何解决您的虚拟主机中有文件触发了安全防护报警规则,可能存在webshell网页木马...
  13. Linux Centos7 测试硬盘IO速度
  14. 你为什么要进入IT行业呢?
  15. Source Insight 4.0.0086 Patched
  16. 英语发音规则---F字母
  17. Traffic Flow Prediction Using Graph Convolution Neural NetworksOC 翻译笔记
  18. 基于51单片机俄罗斯方块游戏电路设计
  19. 联想g40改Android,求大神帮忙,联想g40如何改win7系统?
  20. python从入门到入土表情包-Python自动生成表情包,python在手,从此斗图无敌手

热门文章

  1. *【牛客 - 326B】背单词(线性dp)
  2. *【UVA - 10382】Watering Grass(贪心,区间覆盖问题,思维)
  3. java 与 xml_xml与java对象转换
  4. python 0o_Python 中的比较:is 与 ==
  5. nodejs 监控linux,linuxServerMonitoring
  6. burpsuite csrf攻击_WEB安全之CSRF
  7. c语言函数大全语法下载,C语言函数大全(语法).doc
  8. app中使用用户名/邮箱/手机号登录的思路分析
  9. redis——缓存击穿/穿透/雪崩
  10. mysql数据库表的导入导出