当前位置: 首页 > news >正文

dede手机网站模板哦外贸公司网站建设方案

dede手机网站模板哦,外贸公司网站建设方案,产品如何推广市场,天津百度推广电话1 多线程和异步的区别 多线程 ≠ 异步 多线程经常会阻塞,而异步不阻塞多线程和异步的使用场景不同 1.1 多线程使用场景适合CPU密集型操作适合长期运行的任务 多线程适合比较耗时的任务,或者需要长期运行的任务,它会充分调动CPU的某一个核去进…

1 多线程和异步的区别

多线程 ≠ 异步

  1. 多线程经常会阻塞,而异步不阻塞
  2. 多线程和异步的使用场景不同

1.1 多线程使用场景

  • 适合CPU密集型操作

  • 适合长期运行的任务
    多线程适合比较耗时的任务,或者需要长期运行的任务,它会充分调动CPU的某一个核去进行相应的计算。使用多线程很多的一个场景就是,在后台开一个轮询。

  • 线程的创建销毁开销比较大
    异步默认借助线程池,线程池的开销就小很多。

  • 提供更底层的控制,操作线程,锁,信号
    线程是一个比较底层的功能,所以提供了更底层的控制,比如线程锁,信号量等等,但是异步其实对于线程池的封装,这样就不能很好地进行底层的操作。

  • 线程不易于传参及返回
    传参的话可以在Thread.Start里面去传参,但是如果你希望它返回一个结果,那就有点麻烦了,你可能不得不借助全局变量,或者回调函数,同时你还需要在某些地方去阻塞,从而等待某个线程的结束,这样才能保证那个线程已经计算出了结果。

  • 线程的代码书写较为繁琐
    尤其是当你任务比较多,任务之间可能还有一些顺序先后关系,这种情况下你的代码可能
    会显得非常繁琐,但是如果采用异步编程,使用async await 可以非常灵活的去实现这些功能。

1.2 异步使用场景

  • 适合IO密集型操作

  • 适合短暂的小任务
    若频繁访问IO操作,这种情况下比较适用异步编程,因为它比较适合短暂且频繁的小任务,而不是使用多线程。因为线程开出来后,你肯定是希望它多干一会活,毕竟线程的创建开销比较大。但是如果只是一个几十,几百毫秒的小任务,这时候使用多线程就显得不划算了。

  • 避免线程阻塞,提高系统的响应能力
    更重要的是,它不是线程,它不会阻塞线程,所以它可以提高系统的响应能力。一种使用场景是,在UI线程上调用一个方法,若这个方法阻塞了,则UI就会卡顿,这种情况下就需要使用异步。

2 异步任务

2.1 Task 是一个包含异步任务状态的引用类型

task.Id.ToString(); // 获取任务的唯一标识符task.IsFaulted.ToString(); // 获取一个值,该值指示任务是否已因未处理的异常而完成task.IsCanceled.ToString(); // 获取一个值,该值指示任务是否已被取消task.IsCompleted.ToString(); // 获取一个值,该值指示任务是否已完成task.Exception?.ToString(); // 获取导致任务失败的未处理异常的聚合task.CreationOptions.ToString(); // 获取任务的创建选项task.Status.ToString(); // 获取任务的当前状态

2.1 Task 是对于异步任务的抽象

  1. 开启了异步任务之后,当前线程并不会阻塞,而是去做其它事情
  2. 异步任务(默认)会借助线程池在其它线程上运行
  3. 获取结果后回到之前的状态

2.3 任务的结果

1.返回值为Task 表示异步任务没有返回值

  1. 返回值为Task 则表示异步任务有类型为T的返回值

3 异步方法 (Async Task)

3.1 将异步方法标记为async 之后,就可以在方法中使用await 关键字

await XXX 这个XXX 可以是 Task 也可以是 async Task 类型。

3.2 await 关键字会等待异步任务的结束,并获得结果

await 前后会切换线程

若不想切换线程可使用 Task 的 ConfigureAwait(true); //这里配置ConfigureAwait为true,可以回到之前的线程

你想回到之前的线程,你必须得有一个同步上下文。但是对于一个控制台应用程序,它默认是没有上下文的。只有Windform WPF这些程序,也就是UI线程,它默认是有同步上下文的。因为它要保证UI线程需要拥有UI线程上的全部的资源,比如按钮,TextBox这些东西,任何的这些操作都需要发生在UI线程上,而控制台程序就没有这些要求了。
所以,这里总的来说await关键字会等待异步任务的结束,并获得结果,这里的await Task.Delay(1000)就相当于一个异步任务,但是这里是没有返回值的。再比如我们看下面这个例子:

3.3 async + await 会将方法包装成状态机,await 类似于检查点

3.4 Async Task

  1. 返回值依旧是Task 类型 但是在其中可以使用 await 关键字
  2. 在其中写返回值可以直接写Task 中返回类型
public Task Run1()
{return Task.Delay(1000);  // 必须返回Task
}public async Task Run2()
{await Task.Delay(1000);    // 没有返回值 
}
public async Task<string> Run3()
{await Task.Delay(1000);    // 没有返回值 return "Hello";  // 返回值
}

3.4 Async void

  1. 同样是状态机,但缺失记录状态的Task 对象
    Task 状态机是 AsyncTaskMethodBuilder 现在是 AsyncVoidMethodBuilder
    async void 方法里面可以使用await, 但是调用的地方没办法使用await ,因为它的返回值是void,不是Task 。所以也没办法知道异步任务的返回值和状态。
public async void Run4()
{await Task.Delay(1000);    // 没有返回值 
}public async void Run5()
{Run4();    // 这里没办法用 await
}
  1. 无法聚合异常(AggregateException), 需谨慎处理异常
    最需要注意的是,Async void 没有办法获取异常任务的报错信息。如果有Task,Task 会把收集异常报错信息做成汇总,就叫做AggregateException 聚合异常,现在没有Task ,就没有办法实现这个功能。报错会直接抛出。

async void 捕获不了异常
在这里插入图片描述
async Task 可捕获到异常

修改成 Run7().wait()
在这里插入图片描述
修改成 Run7().GetAwaiter().GetResult();
在这里插入图片描述
3. 几乎只对于事件的注册
上面提到 async void 这么危险 但 并不是所有的情况下都使用 async task 就可以了呢 ,有一种情况根本用不了 async Task,那就是对于事件的注册,尤其是WPF里面的Click 这些事件。

3.6 异步编程具有传染性

  1. 一处async 处处async
  2. 几乎所有自带的方法都提供了异步的版本
    。。。

4 异步编程的重要思想

  1. await 会暂时释放当前线程,使得线程可以执行其它工作,而不必阻塞线程直到异步操作完成。

  2. 不要在异步方法里面用任何方式阻塞当前线程

  3. 常见的阻塞情形

  • Task.wait() Task.Result
    若任务没有完成,就会阻塞当前线程,容易造成死锁

  • Task.Delay() Thread.sleep()

  • IO 同步操作的方法

  • 其它繁重且耗时的任务

5 同步上下文

  1. 一中管理和协调线程的机制,允许开发者将代码的执行切换到特点的线程。
    前面异步任务里面线程的切换,都是借助同步上下文来实现的

  2. Winform 和 WPF 具有同步的上下文(UI 线程) ,控制台程序没有

  3. ConfigureAwait(false)

配置人通过await方法结束后是否会回到原来的线程,默认为True,一般只有UI线程会采用这种方式。可以看一下下面代码:

private void Button_Click(object sender, RoutedEventArgs e)
{Debug.WriteLine($"{Thread.CurrentThread.ManagedThreadId}");TestAsync().ConfigureAwait(true);Debug.WriteLine($"{Thread.CurrentThread.ManagedThreadId}");
}public async Task TestAsync()
{await Task.Delay(1000);return;
}

打印结果
在这里插入图片描述

若 不回到之前的线程 则前后线程不一致 ,若更改了控件则会报错,因为控件必须在UI线程上进行修改。

private async void Button_Click(object sender, RoutedEventArgs e)
{Debug.WriteLine($"{Thread.CurrentThread.ManagedThreadId}");await TestAsync().ConfigureAwait(false);this.btn.Content = "完成";Debug.WriteLine($"{Thread.CurrentThread.ManagedThreadId}");
}public async Task TestAsync()
{await Task.Delay(1000);return;
}

在这里插入图片描述
还要注意一个地方:

int result = TestAsync().Result; // 容易造成死锁

 private async void Button_Click(object sender, RoutedEventArgs e){Debug.WriteLine($"{Thread.CurrentThread.ManagedThreadId}");int result = TestAsync().Result;this.btn.Content = "完成";Debug.WriteLine($"{Thread.CurrentThread.ManagedThreadId}");}public async Task<int> TestAsync(){await Task.Delay(1000);return 20;}

这里调用.Result阻塞了UI线程,然后TestAsync()方法里面,await Task.Delay(2000);之后希望回到UI线程,可是现在UI线程被阻塞,它需要等异步任务执行完才会释放,所以导致了死锁。解决方法为:
async Task TestAsync()
{
await Task.Delay(2000).ConfigureAwait(false);
return 10;
}

异步任务 需要 UI线程 但UI线程现在处于阻塞状态
UI线程需要 异步任务执行完成 才会释放

5 TaskScheduler

TaskScheduler也可以用来配置同步上下文,控制Task的调度和运行线程,还有设置优先级,上下文及执行状态等。

6. 异步任务的创建

  1. Task.Run()

  2. Task.Factory.StartNew()

Task.Factory.StartNew()相当于Task.Run()的完整版,提供了比Task.Run()更多的功能,比如TaskCreationOptions.LongRunning标记它是一个长时间运行的线程

  1. new Task + Task.Start()
    跟new Thread 和 Thread.Start很像
http://www.dtcms.com/a/489277.html

相关文章:

  • 嘉兴网站建设系统微信开放平台怎么注销账号
  • 做哪些网站比较好的搜索网
  • 淘宝代码网站有哪些西服定制一般多少钱
  • 宣传片拍摄要求大连网站关键字优化
  • 项目网站分析广东网站建设公司哪家好
  • 免费创立网站wordpress选择文章模板
  • 网络网站建网站建设营销的企业
  • 制作php网站wordpress 自定义登录页面模板
  • 汕头做网站的公司成品小说网站源码
  • 沈阳公司网站制作没有服务器建网站
  • 个人网站设计作品展示网站集约化建设试点
  • 厦门网站建设一般多少钱如何学做网站优化
  • 做设计在哪个网站上找高清图片晋江市建设招投标网站
  • .net购物网站开发漯河网站推广哪家好
  • 2018做网站前景如何用dw做网站的基本步骤
  • 云南网站建设电话资源分享wordpress
  • 北京政平建设投资集团有限公司网站做爰全过程免费的视网站频
  • 完整企业网站模板金融网站建设银行
  • 泉州建设部网站nginx 网站建设
  • 网站设计过时江阴公司做网站
  • 黄埔五屏网站建设网站建设对企业的作用
  • 品牌宝网站认证做平面设计应该在哪个网站求职
  • .net网站开发实例东莞长安 网站建设
  • 官方网站找做化妆品套盒子网站发布初期的推广
  • 网站设计教程文档开发公司合理化建议
  • 环保产品企业网站建设中国进出口贸易网
  • 北京高端网站建设入门网站后台添加关键词
  • 快速网站排名优化云南建个网站哪家便宜
  • 网站建设和推广的话术云南做企业网站多少钱
  • 杭州外贸网站建设公司申跃seo专业培训课程