• 对Asp.net WebApi中异步(async+await)接口实际使用及相关思考(示例给出了get,post,提交文件,异步接口等实践).


    【很多初学者的疑问】

      为何作为web api这样的天然的并发应用,还需要在controller的action上声明使用async这些呢?

      <参考解答>

    在 web 服务器上,.NET Framework 维护用于处理 ASP.NET 请求的线程池。 当请求到达时,将调度池中的线程以处理该请求。 如果以同步方式处理请求,则处理请求的线程将在处理请求时处于繁忙状态,并且该线程无法处理其他请求。
    如果请求发出需要两秒钟时间才能完成的 web 服务调用,则该请求将需要两秒钟,无论是同步执行还是异步执行。 但是,在异步调用期间,线程在等待第一个请求完成时不会被阻止响应其他请求。 因此,当有多个并发请求调用长时间运行的操作时,异步请求会阻止请求队列和线程池的增长。

    [注]总的来说,对单个客户端请求来说,它感受到的速度,响应时间并没有因为使用异步而提升,但对整个服务器来说,因为线程在异步场景下等待的同时还在服务其它的线程,因此线程数不会增长太快,进而不会轻易达到繁忙状态。

    【给出一个自己写的分析代码】

    using ConfigLab.Comp;
    using ConfigLab.Comp.HttpRequestTools.HttpClient;
    using ConfigLab.Comp.MetaData;
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web.Hosting;
    using System.Web.Http;
    
    namespace ConfigLab.WebApiProject.Controllers
    {
        /// <summary>
        /// 功能简介:web api中的异步接口体会
        /// 创建时间:2020-8-23
        /// 创建人:pcw
        /// 备注:如果不需要所有接口有一个默认的 /api/*中的api这段,需要自行修改RouteConfig.cs中的路由设置
        /// </summary>
        public class CommonAPIController : ApiController
        {
            /// <summary>
            /// https://localhost:44305/CommonAPI/getTest1?userid=u001
            /// </summary>
            /// <param name="userid"></param>
            /// <returns></returns>
            public string getTest(string userid)
            {
                return $"test1_result(from web api):userid={userid}";
            }
            /// <summary>
            /// https://localhost:44305/CommonAPI/getTest2
            /// 参数:userid=u002&optype=add
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            [HttpPost]
            public string postTest([FromBody] userActin data)
            {
                return $"test2_result(from web api):userid={data.userid},optype={data.optype}";
            }
            /// <summary>
            /// 请求地址:https://localhost:44305/CommonAPI/postListByAsync
            /// 参数:userid=u002&optype=add
            /// 返回:多个网站的返回值
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            public async Task<List<ResponseResult>> postListByAsync([FromBody] userActin data)
            {
                List<ResponseResult> listResult = new List<ResponseResult>();
                HttpClientAssisterAsync httpAssist = new HttpClientAssisterAsync();//介绍(https://www.cnblogs.com/taohuadaozhu/p/13548266.html),Nuget 搜索安装: ConfigLab.Comp即可使用
                Task<ResponseResult> tsk_rrs = httpAssist.SendRequestByGet("http://www.baidu.com");
                await tsk_rrs;
                listResult.Add(tsk_rrs.Result);
                tsk_rrs = httpAssist.SendRequestByGet("http://www.ifeng.com");
                await tsk_rrs;
                listResult.Add(tsk_rrs.Result);
                return listResult;
            }
            /// <summary>
            /// 请求地址:https://localhost:44305/CommonAPI/SaveFile?projectId=p001&userid=u003
            /// 附加参数:文件流
            /// </summary>
            /// <param name="projectId"></param>
            /// <param name="userid"></param>
            /// <returns></returns>
            public async Task<RunResult> SaveFile(string projectId, string userid)
            {
                RunResult rrs = new RunResult();
                if (!Request.Content.IsMimeMultipartContent())
                {
                    //throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
                    return new RunResult() { RunCode = -1, RunMsg = "HttpStatusCode.UnsupportedMediaType" };
                }
                //string root = Path.Combine(HostingEnvironment.MapPath(ConfigurationManager.AppSettings["FileStorePath"]), DateTime.Now.ToShortDateString(), projectId);
                string root = Path.Combine(ConfigurationManager.AppSettings["FileStorePath"], DateTime.Now.ToShortDateString(), projectId);
                if (!Directory.Exists(root)) Directory.CreateDirectory(root);
                MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(root);
                try
                {
                    await Request.Content.ReadAsMultipartAsync(provider); 
                    return new RunResult() { RunCode = 0, RunMsg = "" };
                }
                catch (Exception ex)
                {
                    rrs.RunCode = -2;
                    rrs.RunMsg = $"获取客户端上传的文件流失败,ex.msg={ex.Message},ex.stacktrace={ex.StackTrace}";
                }
                return rrs;
            }
        }
        /// <summary>
        /// 测试用的post参数对象
        /// </summary>
        public class userActin
        {
            public string userid { get; set; }
            public string optype { get; set; }
    
        }
    }

        

  • 相关阅读:
    使用Python开发IOT Edge应用(2)
    使用Python开发IOT Edge应用(1)
    使用Harbor+Auzre IOT Edge构建智能边界(2)
    使用Harbor+Auzre IOT Edge构建智能边界
    Linux开发人员玩转HDInsight集群上的MapReduce
    将人工智能带到物联网边界设备(2)
    将人工智能带到物联网边界设备(1)
    oracle误删存储过程
    ORACLE审计
    ESXI将虚拟机厚置备转换成精简置备
  • 原文地址:https://www.cnblogs.com/taohuadaozhu/p/13548712.html
Copyright © 2020-2023  润新知