I'm trying to figure what is the best approach, apart of synchronous programming, for doing some EF6 queries that retrieve data. I'll post here all 5 methods(these take place in a 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
}
Methods implementation:
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);
}
- If I understood correctly,
await
for 2 tasks(like in C2 and C2.1) does not make them run in parallel(not even in C.1 example where I launch them first then await), it just frees the current thread and gives them to another 2 different threads that will deal with those tasks - Task.Run() will in fact do just as Invoke.Parallel does, spreading the work on 2 different CPU's for making them run in parallel
- Launching them first and then awaiting (C.1 example) shouldn't make them run a some sort of parallel way?
- Would it be better not using async or parallel at all?
Please make me understand on these examples how can I have async and also better performance, also if there are any implications with EntityF that I must consider. I'm reading for a few days already and I only get confused, so please don't give me another links to read :)