网站首页 > 博客文章 正文
await关键字可以简便地附加延续。
static void Main(string[] args)
{
DisplayPrimesCount();
}
static async void DisplayPrimesCount()
{
int result = await GetPrimesCountAsync(2, 1000000);
Console.WriteLine(result);
}
/// <summary>
/// 获得素数个数
/// </summary>
/// <param name="start">从什么数开始</param>
/// <param name="count">要获取的连续整数的数目</param>
/// <returns></returns>
static Task<int> GetPrimesCountAsync(int start, int count)
{
return Task.Run(() =>ParallelEnumerable.Range(start, count)
.Count(n => Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0)));
}
添加了async修饰符的方法称为异步函数。 当遇到await表达式时,通常情况下执行过程会返回到调用者上。运行时在返回之前会在等待的任务上附加一个延续,保证任务结束时执行点会跳回到方法中,并继续剩余的代码。如果顺利结束,则返回值为await表达式赋值。 可以以下例子展开形式印证:
static void DisplayPrimesCount()
{
var awaiter = GetPrimesCountAsync(2, 1000000).GetAwaiter() ;
awaiter.OnCompleted(()=>
{
int result = awaiter.GetResult();
Console.WriteLine(result);
});
}
await等待的表达式通常情况下是一个任务。但实际上,只要该对象拥有GetAwaiter方法,且该方法的返回值为等待器,则编译器都可以接受。
await表达式的最大优势在于它几乎可以出现在任何异步函数的表达式中,但不能出现在lock或unsafe上下文中。 以下示例中,await出现在循环结构中:
static async void DisplayPrimesCounts()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(await GetPrimesCountAsync(i * 1000000 + 2, 1000000));
}
}
在第一次执行GetPrimesCountAsync方法时,由于出现了await表达式,因此执行点返回给调用者。当方法完成时,执行点会从停止之处恢复执行,同时保留局部变量和循环计数器的值。
UI上的等待处理
现在将编写一个UI程序,并且使该程序在调用计算密集的方法时仍然保持UI的响应性。 首先示例同步实现:
public partial class TestUI : Window
{
Button _button = new Button { Content = "Go" };
TextBlock _results = new TextBlock();
public TestUI()
{
InitializeComponent();
var panel = new StackPanel();
panel.Children.Add(_button);
panel.Children.Add(_results);
Content = panel;
_button.Click += (sender, args) => Go();
}
void Go()
{
for (int i = 1; i < 5; i++)
{
_results.Text += GetPrimesCount(i * 1000000, 1000000) +
" primes between " + (i * 1000000) + " and " + ((i + 1) * 1000000 - 1) +
Environment.NewLine;
}
}
int GetPrimesCount(int start, int count)
{
return ParallelEnumerable.Range(start, count)
.Count(n =>Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0));
}
}
当点击按钮时,由于执行计算密集代码时间长,程序会陷入无响应状态。 我们可以分两步实现相应的异步方法。 第一步:异步的GetPrimesCount方法
Task<int> GetPrimesCountAsync (int start, int count)
{
return Task.Run (() =>
ParallelEnumerable.Range (start, count).Count (n =>
Enumerable.Range (2, (int) Math.Sqrt(n)-1).All (i => n % i > 0)));
}
第二步:在Go方法中调用
async void Go()
{
_button.IsEnabled = false;
for (int i = 1; i < 5; i++)
_results.Text += await GetPrimesCountAsync (i * 1000000, 1000000) +
" primes between " + (i*1000000) + " and " + ((i+1)*1000000-1) + Environment.NewLine;
_button.IsEnabled = true;
}
由以上代码可见异步函数的简洁性,只需按同步方式书写,并当调用异步函数时进行等待await就可以避免阻塞了。 GetPrimesCountAsync方法会运行在工作线程上,而Go方法则会“租用”UI线程时间,即Go方法在消息循环中是以伪并发的方式执行的。
猜你喜欢
- 2024-10-15 Python 速度慢,试试这个方法提高 1000 倍
- 2024-10-15 C# 文件操作浅析(c#代码文件)
- 2024-10-15 从零开始自学C#基础的第十五天——数组的基本用法
- 2024-10-15 浅谈C#取消令牌CancellationTokenSource
- 2024-10-15 总结了才知道,原来channel有这么多用法
- 2024-10-15 面向对象(8-15)异常类-C#编程零基础到入门学习
- 2024-10-15 .NET 6 中 LINQ 的改进(.net 调优)
- 2024-10-15 Log4net配置文件 C#(c# log4j)
- 2024-10-15 C# BIN文件读取以及CRC校验(匹配STM32F103)
- 2024-10-15 C#如何对String中的Contact/Join方法进行优化的
你 发表评论:
欢迎- 最近发表
-
- 给3D Slicer添加Python第三方插件库
- Python自动化——pytest常用插件详解
- Pycharm下安装MicroPython Tools插件(ESP32开发板)
- IntelliJ IDEA 2025.1.3 发布(idea 2020)
- IDEA+Continue插件+DeepSeek:开发者效率飙升的「三体组合」!
- Cursor:提升Python开发效率的必备IDE及插件安装指南
- 日本旅行时想借厕所、买香烟怎么办?便利商店里能解决大问题!
- 11天!日本史上最长黄金周来了!旅游万金句总结!
- 北川景子&DAIGO缘定1.11 召开记者会宣布结婚
- PIKO‘PPAP’ 洗脑歌登上美国告示牌
- 标签列表
-
- ifneq (61)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)