在wpf命令里使用了await为什么还会阻塞ui

  • ~23.18K 字

在最近在开发中遇到个很有意思的问题,我在一个命令里面使用了一些sql执行操作,虽然这些sql执行都使用了await等待sql耗时操作,但ui还是阻塞了,百思不得其解,思考了半天问了我们组长,组长说在await执行完成后还是会回到ui线程,最好把这些与ui无关代码的用task.run包起来,放在后台线程。

虽然问题成功得到了解决,但对await阻塞了ui线程这个问题还是不解,我们知道await让出了线程,不阻塞ui,等任务完成后会回来继续跑,那它为什么阻塞了ui呢?至少看起来是阻塞了ui。

经查阅资料,实际上await并不会一开始就把所有操作都放在后台,只有遇到了真正的io等待时才会切到后台线程,下面是我在命令里执行的异步方法

代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
public async Task<PerformanceTestResult> DBFilePerformanceTest(string fileName)
{
if (!File.Exists(fileName)) throw new InvalidOperationException("db文件不存在");

if (_settings.PerformanceTestConfig == null)
{
_settings.PerformanceTestConfig = new PerformanceTestConfig();
_settings.SaveConfig();
}

Dictionary<string, object> sheets = [];
List<PerformanceTestReportParsingVolumeDto> sheet1data = [];
List<PerformanceTestReportExportDto> sheet2data = [];

using var fsql = new FreeSqlBuilder().UseConnectionString(DataType.Sqlite, AppBase.GetSqliteConnectionString(fileName)).Build();

#region 低频采样率参数个数 推荐90000

var sql_sumcount_ch10_low = "select count(1) from ch10_parameterid where samplerate<512 ";
var sql_sumcount_npd_low = "select count(1) from npd_parameterid where samplerate<512 ";
var sql_sumcount_npdgd_low = "select count(1) from npdgd_parameterid where samplerate<512 ";
var sql_sumcount_npdx_low = "select count(1) from npdx_parameterid where samplerate<512 ";
var sql_sumcount_para_low = "select count(1) from parameterid where samplerate<512 ";
long? sum_count_ch10_low = 0, sum_count_npd_low = 0, sum_count_npdgd_low = 0, sum_count_npdx_low = 0, sum_count_para_low = 0;
try
{
sum_count_para_low = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_para_low) as long?;
sum_count_para_low = sum_count_para_low is null ? 0 : sum_count_para_low;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_ch10_low = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_ch10_low) as long?;
sum_count_ch10_low = sum_count_ch10_low is null ? 0 : sum_count_ch10_low;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_npd_low = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_npd_low) as long?;
sum_count_npd_low = sum_count_npd_low is null ? 0 : sum_count_npd_low;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_npdgd_low = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_npdgd_low) as long?;
sum_count_npdgd_low = sum_count_npdgd_low is null ? 0 : sum_count_npdgd_low;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_npdx_low = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_npdx_low) as long?;
sum_count_npdx_low = sum_count_npdx_low is null ? 0 : sum_count_npdx_low;
}
catch (Exception ex)
{
_logger.Error(ex);
}
long sum_count_low = sum_count_ch10_low.Value + sum_count_npd_low.Value + sum_count_npdgd_low.Value + sum_count_npdx_low.Value + sum_count_para_low.Value;
if (sum_count_low > _settings.PerformanceTestConfig.LowFreqParaCountMaximum)
{
var data1 = new PerformanceTestReportParsingVolumeDto()
{
Description = $"系统支持解析的低频参数个数最多 {_settings.PerformanceTestConfig.LowFreqParaCountMaximum} 个",
Maximum = _settings.PerformanceTestConfig.LowFreqParaCountMaximum,
CurrentValue = sum_count_low,
OverrunPercentage = $"{(sum_count_low - _settings.PerformanceTestConfig.LowFreqParaCountMaximum) * 1.0 / _settings.PerformanceTestConfig.LowFreqParaCountMaximum:P2}"
};
sheet1data.Add(data1);
}

#endregion 低频采样率参数个数 推荐90000

#region 高频(>=512)采样率参数个数 推荐1500

var sql_sumcount_ch10 = "select count(1) from ch10_parameterid where samplerate>=512 and samplerate<8192 ";
var sql_sumcount_npd = "select count(1) from npd_parameterid where samplerate>=512 and samplerate<8192 ";
var sql_sumcount_npdgd = "select count(1) from npdgd_parameterid where samplerate>=512 and samplerate<8192 ";
var sql_sumcount_npdx = "select count(1) from npdx_parameterid where samplerate>=512 and samplerate<8192 ";
var sql_sumcount_para = "select count(1) from parameterid where samplerate>=512 and samplerate<8192 ";
long? sum_count_ch10 = 0, sum_count_npd = 0, sum_count_npdgd = 0, sum_count_npdx = 0, sum_count_para = 0;
try
{
sum_count_para = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_para) as long?;
sum_count_para = sum_count_para is null ? 0 : sum_count_para;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_ch10 = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_ch10) as long?;
sum_count_ch10 = sum_count_ch10 is null ? 0 : sum_count_ch10;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_npd = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_npd) as long?;
sum_count_npd = sum_count_npd is null ? 0 : sum_count_npd;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_npdgd = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_npdgd) as long?;
sum_count_npdgd = sum_count_npdgd is null ? 0 : sum_count_npdgd;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_npdx = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_npdx) as long?;
sum_count_npdx = sum_count_npdx is null ? 0 : sum_count_npdx;
}
catch (Exception ex)
{
_logger.Error(ex);
}
long sum_count = sum_count_ch10.Value + sum_count_npd.Value + sum_count_npdgd.Value + sum_count_npdx.Value + sum_count_para.Value;
if (sum_count > _settings.PerformanceTestConfig.High512HzParaCountMaximum)
{
var data1 = new PerformanceTestReportParsingVolumeDto()
{
Description = $"系统支持解析的高频参数(>=512Hz)个数最多 {_settings.PerformanceTestConfig.High512HzParaCountMaximum} 个",
Maximum = _settings.PerformanceTestConfig.High512HzParaCountMaximum,
CurrentValue = sum_count,
OverrunPercentage = $"{(sum_count - _settings.PerformanceTestConfig.High512HzParaCountMaximum) * 1.0 / _settings.PerformanceTestConfig.High512HzParaCountMaximum:P2}"
};
sheet1data.Add(data1);
}

#endregion 高频(>=512)采样率参数个数 推荐1500

#region 高频8K采样率参数个数 推荐200

var sql_sumcount_ch10_8k = "select count(1) from ch10_parameterid where samplerate=8192 ";
var sql_sumcount_npd_8k = "select count(1) from npd_parameterid where samplerate=8192 ";
var sql_sumcount_npdgd_8k = "select count(1) from npdgd_parameterid where samplerate=8192 ";
var sql_sumcount_npdx_8k = "select count(1) from npdx_parameterid where samplerate=8192 ";
var sql_sumcount_para_8k = "select count(1) from parameterid where samplerate=8192 ";
long? sum_count_ch10_8k = 0, sum_count_npd_8k = 0, sum_count_npdgd_8k = 0, sum_count_npdx_8k = 0, sum_count_para_8k = 0;
try
{
sum_count_para_8k = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_para_8k) as long?;
sum_count_para_8k = sum_count_para_8k is null ? 0 : sum_count_para_8k;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_ch10_8k = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_ch10_8k) as long?;
sum_count_ch10_8k = sum_count_ch10_8k is null ? 0 : sum_count_ch10_8k;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_npd_8k = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_npd_8k) as long?;
sum_count_npd_8k = sum_count_npd_8k is null ? 0 : sum_count_npd_8k;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_npdgd_8k = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_npdgd_8k) as long?;
sum_count_npdgd_8k = sum_count_npdgd_8k is null ? 0 : sum_count_npdgd_8k;
}
catch (Exception ex)
{
_logger.Error(ex);
}
try
{
sum_count_npdx_8k = await fsql.Ado.ExecuteScalarAsync(sql_sumcount_npdx_8k) as long?;
sum_count_npdx_8k = sum_count_npdx_8k is null ? 0 : sum_count_npdx_8k;
}
catch (Exception ex)
{
_logger.Error(ex);
}
long sum_count_8k = sum_count_ch10_8k.Value + sum_count_npd_8k.Value + sum_count_npdgd_8k.Value + sum_count_npdx_8k.Value + sum_count_para_8k.Value;
if (sum_count_8k > _settings.PerformanceTestConfig.High8192ParaCountMaximum)
{
var data1 = new PerformanceTestReportParsingVolumeDto()
{
Description = $"系统支持解析的高频参数(8192Hz)个数最多 {_settings.PerformanceTestConfig.High8192ParaCountMaximum} 个",
Maximum = _settings.PerformanceTestConfig.High8192ParaCountMaximum,
CurrentValue = sum_count_8k,
OverrunPercentage = $"{(sum_count_8k - _settings.PerformanceTestConfig.High8192ParaCountMaximum) * 1.0 / _settings.PerformanceTestConfig.High8192ParaCountMaximum:P2}"
};
sheet1data.Add(data1);
}

#endregion 高频8K采样率参数个数 推荐200

#region 单条数据流8K采样率参数个数,单条流只查表npd_parameterid 推荐100

var sql_sumsamplerate_groupbyStreamID_8k = "select streamid,sum(1) Count from npd_parameterid where samplerate=8192 group by streamid";
var npdParameterIDGroupByStreamIDDtos_8k = await fsql.Ado.QueryAsync<NPDParameterIDGroupByStreamIDDto>(sql_sumsamplerate_groupbyStreamID_8k);

foreach (var item in npdParameterIDGroupByStreamIDDtos_8k)
{
if (item.Count != null && item.Count > _settings.PerformanceTestConfig.Sample8KSingleStreamParaCountMaximum)
{
var data1 = new PerformanceTestReportParsingVolumeDto()
{
Description = $"单条数据流最多支持 {_settings.PerformanceTestConfig.Sample8KSingleStreamParaCountMaximum} 个 8192 Hz 参数",
Maximum = _settings.PerformanceTestConfig.Sample8KSingleStreamParaCountMaximum,
CurrentValue = item.Count.Value,
OverrunPercentage = $"{(item.Count - _settings.PerformanceTestConfig.Sample8KSingleStreamParaCountMaximum) * 1.0 / _settings.PerformanceTestConfig.Sample8KSingleStreamParaCountMaximum:P2}",
CaseNumber = item.StreamID // 机箱号
};
sheet1data.Add(data1);
}
}

#endregion 单条数据流8K采样率参数个数,单条流只查表npd_parameterid 推荐100

#region 总导出性能 推荐360 * 32 * 1200 13824000

var sql_paramgroups = "select rate,parameters from paramgroups";
var paramgroupsDtos = await fsql.Ado.QueryAsync<ParamGroupsDto>(sql_paramgroups);
double sum_rate = 0;
foreach (var item in paramgroupsDtos)
{
var parameters = Encoding.UTF8.GetString(item.Parameters);
sum_rate += item.Rate * parameters.Split(';').Length;
}

if (sum_rate > _settings.PerformanceTestConfig.ExportVolumeMaximum)
{
var data = new PerformanceTestReportExportDto()
{
Description = $"导出参数资源总和最大支持 {_settings.PerformanceTestConfig.ExportVolumeMaximum} 点/秒",
Maximum = $"{_settings.PerformanceTestConfig.ExportVolumeMaximum}",
CurrentValue = $"{sum_rate}",
OverrunPercentage = $"{(sum_rate - _settings.PerformanceTestConfig.ExportVolumeMaximum) / _settings.PerformanceTestConfig.ExportVolumeMaximum:P2}"
};
sheet2data.Add(data);
}

#endregion 总导出性能 推荐360 * 32 * 1200 13824000

#region 单个低频导出性能 推荐 32hz 1500、128hz 370、256hz 180

var sql_paramgroups_32hz = "select name,rate,parameters from paramgroups where rate = 32";
var sql_paramgroups_128hz = "select name,rate,parameters from paramgroups where rate = 128";
var sql_paramgroups_256hz = "select name,rate,parameters from paramgroups where rate = 256";
var paramgroupsDtos_32hz = await fsql.Ado.QueryAsync<ParamGroupsDto>(sql_paramgroups_32hz);
var paramgroupsDtos_128hz = await fsql.Ado.QueryAsync<ParamGroupsDto>(sql_paramgroups_128hz);
var paramgroupsDtos_256hz = await fsql.Ado.QueryAsync<ParamGroupsDto>(sql_paramgroups_256hz);

foreach (var item in paramgroupsDtos_32hz)
{
string paras = Encoding.UTF8.GetString(item.Parameters);
int paraCount = paras.Split(';').Length;
if (paraCount > _settings.PerformanceTestConfig.SingleExportMaximum_32hz)
{
var data = new PerformanceTestReportExportDto()
{
Description = $"单个低频参数组 32Hz 参数上限 {_settings.PerformanceTestConfig.SingleExportMaximum_32hz}",
Maximum = $"{_settings.PerformanceTestConfig.SingleExportMaximum_32hz}",
CurrentValue = $"{paraCount}",
OverrunPercentage = $"{(paraCount - _settings.PerformanceTestConfig.SingleExportMaximum_32hz) * 1.0 / _settings.PerformanceTestConfig.SingleExportMaximum_32hz:P2}",
GroupName = item.Name,
};
sheet2data.Add(data);
}
}

foreach (var item in paramgroupsDtos_128hz)
{
string paras = Encoding.UTF8.GetString(item.Parameters);
int paraCount = paras.Split(';').Length;
if (paraCount > _settings.PerformanceTestConfig.SingleExportMaximum_128hz)
{
var data = new PerformanceTestReportExportDto()
{
Description = $"单个低频参数组 128Hz 参数上限 {_settings.PerformanceTestConfig.SingleExportMaximum_128hz}",
Maximum = $"{_settings.PerformanceTestConfig.SingleExportMaximum_128hz}",
CurrentValue = $"{paraCount}",
OverrunPercentage = $"{(paraCount - _settings.PerformanceTestConfig.SingleExportMaximum_128hz) * 1.0 / _settings.PerformanceTestConfig.SingleExportMaximum_128hz:P2}",
GroupName = item.Name,
};
sheet2data.Add(data);
}
}

foreach (var item in paramgroupsDtos_256hz)
{
string paras = Encoding.UTF8.GetString(item.Parameters);
int paraCount = paras.Split(';').Length;
if (paraCount > _settings.PerformanceTestConfig.SingleExportMaximum_256hz)
{
var data = new PerformanceTestReportExportDto()
{
Description = $"单个低频参数组 256Hz 参数上限 {_settings.PerformanceTestConfig.SingleExportMaximum_256hz}",
Maximum = $"{_settings.PerformanceTestConfig.SingleExportMaximum_256hz}",
CurrentValue = $"{paraCount}",
OverrunPercentage = $"{(paraCount - _settings.PerformanceTestConfig.SingleExportMaximum_256hz) * 1.0 / _settings.PerformanceTestConfig.SingleExportMaximum_256hz:P2}",
GroupName = item.Name,
};
sheet2data.Add(data);
}
}

#endregion 单个低频导出性能 推荐 32hz 1500、128hz 370、256hz 180

#region 单个高频导出性能 推荐 512hz 150、1024hz 100、8192hz 20、16384hz 8

var sql_paramgroups_512hz = "select name,rate,parameters from paramgroups where rate = 512";
var sql_paramgroups_1024hz = "select name,rate,parameters from paramgroups where rate = 1024";
var sql_paramgroups_8192hz = "select name,rate,parameters from paramgroups where rate = 8192";
var sql_paramgroups_16384hz = "select name,rate,parameters from paramgroups where rate = 16384";
var paramgroupsDtos_512hz = await fsql.Ado.QueryAsync<ParamGroupsDto>(sql_paramgroups_512hz);
var paramgroupsDtos_1024hz = await fsql.Ado.QueryAsync<ParamGroupsDto>(sql_paramgroups_1024hz);
var paramgroupsDtos_8192hz = await fsql.Ado.QueryAsync<ParamGroupsDto>(sql_paramgroups_8192hz);
var paramgroupsDtos_16384hz = await fsql.Ado.QueryAsync<ParamGroupsDto>(sql_paramgroups_16384hz);

foreach (var item in paramgroupsDtos_512hz)
{
string paras = Encoding.UTF8.GetString(item.Parameters);
int paraCount = paras.Split(';').Length;
if (paraCount > _settings.PerformanceTestConfig.SingleExportMaximum_512hz)
{
var data = new PerformanceTestReportExportDto()
{
Description = $"单个高频参数组 512Hz 参数上限 {_settings.PerformanceTestConfig.SingleExportMaximum_512hz}",
Maximum = $"{_settings.PerformanceTestConfig.SingleExportMaximum_512hz}",
CurrentValue = $"{paraCount}",
OverrunPercentage = $"{(paraCount - _settings.PerformanceTestConfig.SingleExportMaximum_512hz) * 1.0 / _settings.PerformanceTestConfig.SingleExportMaximum_512hz:P2}",
GroupName = item.Name,
};
sheet2data.Add(data);
}
}
foreach (var item in paramgroupsDtos_1024hz)
{
string paras = Encoding.UTF8.GetString(item.Parameters);
int paraCount = paras.Split(';').Length;
if (paraCount > _settings.PerformanceTestConfig.SingleExportMaximum_1024hz)
{
var data = new PerformanceTestReportExportDto()
{
Description = $"单个高频参数组 1024Hz 参数上限 {_settings.PerformanceTestConfig.SingleExportMaximum_1024hz}",
Maximum = $"{_settings.PerformanceTestConfig.SingleExportMaximum_1024hz}",
CurrentValue = $"{paraCount}",
OverrunPercentage = $"{(paraCount - _settings.PerformanceTestConfig.SingleExportMaximum_1024hz) * 1.0 / _settings.PerformanceTestConfig.SingleExportMaximum_1024hz:P2}",
GroupName = item.Name,
};
sheet2data.Add(data);
}
}
foreach (var item in paramgroupsDtos_8192hz)
{
string paras = Encoding.UTF8.GetString(item.Parameters);
int paraCount = paras.Split(';').Length;
if (paraCount > _settings.PerformanceTestConfig.SingleExportMaximum_8192hz)
{
var data = new PerformanceTestReportExportDto()
{
Description = $"单个高频参数组 8192Hz 参数上限 {_settings.PerformanceTestConfig.SingleExportMaximum_8192hz}",
Maximum = $"{_settings.PerformanceTestConfig.SingleExportMaximum_8192hz}",
CurrentValue = $"{paraCount}",
OverrunPercentage = $"{(paraCount - _settings.PerformanceTestConfig.SingleExportMaximum_8192hz) * 1.0 / _settings.PerformanceTestConfig.SingleExportMaximum_8192hz:P2}",
GroupName = item.Name,
};
sheet2data.Add(data);
}
}
foreach (var item in paramgroupsDtos_16384hz)
{
string paras = Encoding.UTF8.GetString(item.Parameters);
int paraCount = paras.Split(';').Length;
if (paraCount > _settings.PerformanceTestConfig.SingleExportMaximum_16384hz)
{
var data = new PerformanceTestReportExportDto()
{
Description = $"单个高频参数组 16384Hz 参数上限 {_settings.PerformanceTestConfig.SingleExportMaximum_16384hz}",
Maximum = $"{_settings.PerformanceTestConfig.SingleExportMaximum_16384hz}",
CurrentValue = $"{paraCount}",
OverrunPercentage = $"{(paraCount - _settings.PerformanceTestConfig.SingleExportMaximum_16384hz) * 1.0 / _settings.PerformanceTestConfig.SingleExportMaximum_16384hz:P2}",
GroupName = item.Name,
};
sheet2data.Add(data);
}
}

#endregion 单个高频导出性能 推荐 512hz 150、1024hz 100、8192hz 20、16384hz 8

if (sheet1data.Count > 0)
{
sheets.Add("解析性能", sheet1data);
}
if (sheet2data.Count > 0)
{
sheets.Add("参数组存储性能", sheet2data);
}

if (sheets.Count > 0)
{
return new PerformanceTestResult { IsPass = false, ReportPath = saveFileDialog.FileName, ReportExportItems = sheet2data, ReportParserItems = sheet1data };
}

return new PerformanceTestResult { IsPass = true };
}

public class PerformanceTestResult
{
public bool IsPass { get; set; }
public string ReportPath { get; set; }
public List<object>? ReportParserItems { get; set; }
public List<object>? ReportExportItems { get; set; }
}

里面很多代码其实是在ui线程跑的,如代码里面很多for循环、逻辑计算、对象创建、ORM 解析… 都是cpu代码,不会自动切换线程的,只有到底层io调用时,如 fsql.Ado.ExecuteScalarAsync 才会释放ui线程,而fsql.Ado.ExecuteScalarAsync里面也并不会全程在后台线程执行,如sqlite的官方异步方法它里面根本就没有真正的异步io,因为它是嵌入式数据库,读写本地文件,而Windows底层限制,读写磁盘文件不支持异步操作,里面实际上是同步方法。

并非只要带async、只要加 await,就不在ui线程,async只是提供「io等待时可以让出线程」的能力,但方法开头的一堆前置cpu逻辑,依旧原地阻塞当前线程。

所以,把这些循环、计算、对象创建放到task.run里面吧!当然也可以用ConfigureAwait(false)让await完成后要不要切回原线程,但管不了await之前的前置cpu逻辑。