async和await总结
- 在C#中, async标记了一个包含异步执行的函数,通过async标记的函数若在主线程中直接调用,则函数一开始仍在主线程中执行;
aysnc标记的函数内部必须包含await标记需要异步执行的函数(根据vs2017编译提示),若当前函数在主线程中直接调用,则await标记前的代码在主线程中执行,await标记后的代码在其异步子线程中执行;
async标记的函数返回值必须为void、Task、Task< TResult> 类型,可以理解为async标记的函数返回的是 “空”、“即将执行的任务”、“带结果的即将执行的任务”实例;
async标记的函数可以继续往下调用async标记函数,从调用逻辑可以理解为await实际上用来触发所标记的Task任务异步执行,并最后获取异步执行的返回值,从运行过程看该触发应该仅对最终的Task任务有效。
C#中async与await异步编程
- async声明了一个包含异步执行代码的函数,该函数执行时不会阻塞调用线程;
await存在于async函数中,声明了一个异步执行入口,程序动态运行时从该入口创建并进入一个异步线程环境,并在该线程执行任务实例及任务实例返回之后的代码;
一个async函数中声明多个await关键字时,程序将代码顺序创建并进入异步子线程执行任务实例及任务实例返回之后的代码直到下一个await声明处, 最后一个await声明之后的代码会在最后一个异步子线程中执行 ;
await标记的右侧代码返回或定义了一个任务实例,该实例由需要异步执行的目标耗时函数初始化,并在最终定义处触发异步执行。
用法
- async 用在方法定义前面,await只能写在带有async标记的方法中。
- 注意await异步等待的地方,await后面的代码和前面的代码执行的线程可能不一样
- async关键字创建了一个状态机,类似yield return 语句;await会解除当前线程的阻塞,完成其他任务
同步
比如写ProgressBarItem时不用async异步和Task接口,返回时,直接return model
private ProgressBarViewModel GetProgressBarItem(string connKey, string projectId)
{
var model = new ProgressBarViewModel();
_projectDbContext = DDDbContextFactory.Create(connKey);
//先过滤掉不想要的条件
var exectedScenes = _projectDbContext.SceneResults.Where(t => t.Ratio != "0" && (DateTime.Now - DateTime.Parse(t.StartTime)).TotalSeconds > 0);
//根据不同情况判断
string progressBarDesc = string.Empty;
if(exectedScenes.Any(t=> decimal.Parse(t.Ratio) < 1.0m))
{
progressBarDesc = exectedScenes.Min(t => decimal.Parse(t.Ratio)).ToString();
}
else
{
progressBarDesc = "1";
}
model.ProjectId = projectId;
model.ConnKey = connKey;
model.ProgressBar = progressBarDesc;
return model;
}
异步
private async Task<StatusViewModel> GetIssuccessItem(string connKey, string projectId)
{
var model = new StatusViewModel();
_projectDbContext = DDDbContextFactory.Create(connKey);
model.ProjectId = projectId;
model.ConnKey = connKey;
model.IsSuccess = (await _projectDbContext.SceneResults.Where(t => t.IsSuccess == "0").CountAsync()) > 0 ? "0" : "1";
return model;
}
异步时用await形式对应assync