• 异步编程和跨域请求(04)


     目录:

    • 异步编程
    • 跨域请求

    一.异步编程

    • 线程池

       创建的线程存起来,形成一个线程池(里面有多个线程),当要处理任务时,若线程池中有空闲线程(前一个任务执行完成后,线程不会被回收,会被设置为空闲状态),则直接调用线程池中的线程执行。

    • Task 和 Task<TResult>

      Task是.NET4.0加入的,跟线程池ThreadPool的功能类似,用Task开启新任务时,会从线程池中调用线程,而Thread每次实例化都会创建一个新的线程。

    Console.WriteLine("主线程启动");
    Task task = Task.Run(() => {  //开启新任务的方法:Task.Run()或者Task.Factory.StartNew(),开启的是后台线程。
        Thread.Sleep(1500);
        Console.WriteLine("task启动");
    });
    task.Wait();  //主线程中等待后台线程执行完毕。不用Wait则会以异步的方式来执行。
    Console.WriteLine("主线程结束");
    //---------------------------------------------------------------------------------
    //Task<TResult>

    Console.WriteLine("主线程开始");

        //返回值类型为string

        Task<string> task = Task<string>.Run(() => {  //Task<TResult>就是有返回值的Task,TResult就是返回值类型。

            Thread.Sleep(2000);

            return "任务返回的结果";

        });

        //会等到task执行完毕才会输出;

        Console.WriteLine(task.Result);

        Console.WriteLine("主线程结束");

      通过task.Result可以取到返回值,若取值的时候,后台线程还没执行完,则会等待其执行完毕。

    • async/await

      C# 5.0中引入了async 和 await。这两个关键字可以让你更方便的写出异步代码。

    static Task<string> GetString()
        {
            //Console.WriteLine("GetString方法开始执行")
            return Task<string>.Run(() =>
            {
                Thread.Sleep(2000);
                return "GetString的返回值";
            });
        }static async Task<int> GetStrLengthAsync()
        {
            Console.WriteLine("GetStrLengthAsync方法开始执行");
            //此处返回的<string>中的字符串类型,而不是Task<string>
            string str = await GetString();  //await不会阻塞主线程,只会让GetStrLengthAsync方法暂停执行。
            Console.WriteLine("GetStrLengthAsync方法执行结束");
            return str.Length;
    }
    static void Main(string[] args)
        {
            Console.WriteLine("-------主线程启动-------");
            Task<int> task = GetStrLengthAsync();
            Console.WriteLine("主线程继续执行");
            Console.WriteLine("Task返回的值" + task.Result);
            Console.WriteLine("-------主线程结束-------");
            Console.Read();
    }

    运行效果:

      async用来修饰方法,表明这个方法是异步的,声明的方法的返回类型必须为:void,Task或Task<TResult>。
      await必须用来修饰Task或Task<TResult>,而且只能出现在已经用async关键字修饰的异步方法中。通常情况下,async/await成对出现才有意义。
    •  在ASP.NET Web API中使用async/await

       当在数据库中执行查询时,异步查询可避免阻止线程。异步操作还可以增加 Web 应用程序的吞吐量,可以在数据库操作完成时释放线程去处理其他请求。

      //异步查询
    public async Task<IHttpActionResult> GetStudentAsync()
    {
        Student student = null;
        using (var context = new SchoolDBEntities())
        {
             //注意await和FirstOrDefaultAsync
            student = await (context.Students.Where(s => s.StudentID == 1).FirstOrDefaultAsync<Student>());
        }
        return Json(student);
    }
    //异步保存 public async Task<IHttpActionResult> Put(Student stu) { using (var context = new SchoolDBEntities()) { context.Entry(stu).State = EntityState.Modified; int x = await (context.SaveChangesAsync()); return Ok("保存完成"); } }

      在System.Data.Entit.QueryableExtensions 扩展类中,提供了一系列异步方法,如:FirstOrDefaultAsync()、ToListAsync()、ToArrayAsync()、SingleAsync()等。另外还有DbContext对象的SaveChangesAsync()方法。

    二.跨域请求

    • 跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。
    • 所谓的同源是指:域名、协议、端口均为相同。
    • 同源策略限制了以下行为:Cookie、LocalStorage 和 IndexDB 无法读取  ||  DOM 和 JS 对象无法获取  ||  Ajax请求发送不出去
    • 常见的跨域场景

    URL

    说明

    是否允许

    http://www.aoxiang.cn/index.html

    http://www. aoxiang.cn/server.php

    非跨域

    允许

    http://www. aoxiang.cn/index.html

    http://www.neal.cn/server.php

    跨域,主域不同

    不允许

    http://abc. aoxiang.cn/index.html

    http://def. aoxiang.cn/server.php

    跨域,子域名不同

    不允许

    http://www.aoxiang.cn:8080/index.html

    http://www. aoxiang.cn/server.php

    跨域,端口不同

    不允许

    https://www. aoxiang.cn/index.html

    http://www. aoxiang.cn/server.php

    跨域,协议不同

    不允许

    当发生跨域时,经常会引发如下形式的异常。

    • 跨域问题的解决方案

      1.Mvc和WebApi通用的模式

      只需要在WebConfig中进行配置,缺点是只能进行全局配置。

    <system.webServer>
        <!--允许跨域请求的配置  WebApi和MVC通用-->
        <httpProtocol>
          <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Headers" value="Access-Control-Allow-Origin, AppKey, Authorization"/>
            <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
            <add name="Access-Control-Request-Methods" value="GET, POST, OPTIONS" />
          </customHeaders>
        </httpProtocol>
        <!--允许跨域请求的配置  WebApi和MVC通用   至此结束-->
        <!—略……-->
      </system.webServer>

    其中,

          l  Access-Control-Allow-Origin :代表允许请求的地址,如:" http://localhost:2131, http://localhost:2133" 多个地址之间用逗号隔开,*  代表运行所有

          l  Access-Control-Allow-headers: 代表允许的表头

          l  Access-Control-Allow-method: 代表允许请求的方法。如:"GET,PUT,POST,DELETE"

     2. WebApi特有的处理方式

    • 首先通过Nuget添加【Microsoft.AspNet.WebApi.Cors】程序集。
    • 核心方法:EnableCorsAttribute(string origins, string headers, string methods)

        分别表示:origins代表允许请求的地址:" http://localhost:2131, http://localhost:2133" 多个地址之间用逗号隔开。

             headers代表允许的表头。

             method代表允许请求方法:"GET,PUT,POST,DELETE"

             * 代表允许所有。

    • 可以作用于全局,也可以特性的形式作用于Controller,或者直接作用于Action。

       1.作用于全局

        在WebApiConfig类中的Register方法中添加:config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

       2. 作用于Controller

        (1). 在WebApiConfig类中的Register方法中添加:config.EnableCors();

        (2). 在FifthController控制器上添加特性:[EnableCors("*", "*", "*")]

       3. 作用于Action

        (1). 在WebApiConfig类中的Register方法中添加:config.EnableCors();

        (2). 在GetUserName2方法上添加特性:[EnableCors("*", "*", "*")]

      部分代码如下所示:

  • 相关阅读:
    Android中layout_gravity和gravity的区别
    Android基础面试题
    小白学习设计模式之工厂模式
    装饰者模式视频示例
    小白学习设计模式之装饰者模式
    利用poi来向execl中写入对象
    java利用poi来读取execl表格返回对象
    java小白设计模式之观察者模式
    小白学习java设计模式之策略模式
    如何理解java是一个面向对象的语言?(转自Hollis的直面java)
  • 原文地址:https://www.cnblogs.com/shishixiang/p/14000401.html
Copyright © 2020-2023  润新知