我试图弄清楚除了同步编程之外,执行一些检索数据的 EF6 查询的最佳方法是什么。我将在这里发布所有 5 种方法(这些方法发生在 Controller Action 中):
//would it be better to not "async" the ActionResult?
public async Task<ActionResult> Index{
// I depend on this so I don't even know if it's ok to make it async or not -> what do you think?
var userinfo = _dataservice.getUserInfo("John");
// C1: synchronous way
var watch1 = System.Diagnostics.Stopwatch.StartNew();
var info1 = _getInfoService.GetSomeInfo1(userinfo);
var info2 = _getInfoService.GetSomeInfo2(userinfo);
watch1.Stop();
var t1 = watch.EllapsedMilliSeconds; // this takes about 3200
// C2: asynchronous way
var watch2 = System.Diagnostics.Stopwatch.StartNew();
var infoA1 = await _getInfoService.GetSomeInfoAsync1(userinfo).ConfigureAwait(false);
var infoA2 = await _getInfoService.GetSomeInfoAsync2(userinfo).ConfigureAwait(false);
watch2.Stop();
var t2 = watch2.EllapsedMilliSeconds; // this takes about 3020
// C2.1: asynchronous way launch then await
var watch21 = System.Diagnostics.Stopwatch.StartNew();
var infoA21 = _getInfoService.GetSomeInfoAsync1(userinfo).ConfigureAwait(false);
var infoA22 = _getInfoService.GetSomeInfoAsync2(userinfo).ConfigureAwait(false);
// I tought if I launch them first then await, it would run faster...but not
var a = await infoA21;
var b = await infoA22;
watch21.Stop();
var t21 = watch21.EllapsedMilliSeconds; // this takes about the same 30201
// C3: asynchronous with Task.Run() and await.WhenAll()
var watch1 = System.Diagnostics.Stopwatch.StartNew();
var infoT1 = TaskRun(() => _getInfoService.GetSomeInfo1(userinfo));
var infoT2 = TaskRun(() => _getInfoService.GetSomeInfo2(userinfo));
await Task.WhenAll(infoT1,infoT2)
watch3.Stop();
var t3 = watch3.EllapsedMilliSeconds; // this takes about 2010
// C4: Parallel way
MyType var1; MyType2 var2;
var watch4 = System.Diagnostics.Stopwatch.StartNew();
Parallel.Invoke(
() => var1 = _getInfoService.GetSomeInfoAsync1(userinfo).GetAwaiter().GetResult(),// also using just _getInfoService.GetSomeInfo1(userinfo) - but sometimes throws an Entity error on F10 debugging
() => var2 = _getInfoService.GetSomeInfoAsync2(userinfo).GetAwaiter().GetResult()// also using just _getInfoService.GetSomeInfo2(userinfo)- but sometimes throws an Entity error on F10 debugging
);
watch4.Stop();
var t4 = watch4.EllapsedMilliSeconds; // this takes about 2012
}
方法实现:
public MyType1 GetSomeInfo1(SomeOtherType param){
// result = some LINQ queries here
Thread.Sleep(1000);
return result;
}
public MyType2 GetSomeInfo2(SomeOtherType param){
// result = some LINQ queries here
Thread.Sleep(2000);
return result;
}
public Task<MyType1> GetSomeInfoAsync1(SomeOtherType param){
// result = some LINQ queries here
Thread.Sleep(1000);
return Task.FromResult(result);
}
public Task<MyType2> GetSomeInfoAsync2(SomeOtherType param){
// result = some LINQ queries here
Thread.Sleep(2000);
return Task.FromResult(result);
}
- 如果我理解正确,
await
对于 2 个任务(例如在 C2 和 C2.1 中)不会使它们并行运行(甚至在我先启动它们然后等待的 C.1 示例中也不),它只是释放当前线程并给它们到另外 2 个不同的线程来处理这些任务 - Task.Run() 实际上会像 Invoke.Parallel 那样做,将工作分散到 2 个不同的 CPU 上,使它们并行运行
- 先启动它们然后等待(C.1 示例)不应该使它们以某种并行方式运行吗?
- 完全不使用异步或并行会更好吗?
请让我了解这些示例如何获得异步和更好的性能,如果我必须考虑对 EntityF 的任何影响。我已经读了几天了,我只是感到困惑,所以请不要给我另一个阅读链接:)