Twilight
Asynchronous programming C#
  1. CAsync2 myc = new CAsync2();
  2. await myc.SomeEnd1();
  3. await myc.SomeEnd2();
  4. public class CAsync2
  5. {
  6. public async Task M1()
  7. {
  8. await Task.Delay(4000);
  9. Console.Write("M1");
  10. }
  11. public Task M2()
  12. {
  13. Console.WriteLine("M2");
  14. return Task.CompletedTask;
  15. }
  16. public async Task SomeEnd1()
  17. {
  18. await M1();
  19. await M2();
  20. }
  21. public async Task SomeEnd2()
  22. {
  23. var t1 = M1();
  24. var t2 = M2();
  25. await t1;
  26. await t2;
  27. }
  28. }

What is the result and why?

By Twilight in .NET on Aug 07 2022
  • Larry Dukek
    Sep, 2022 21

    Result:

    1. M1M2
    2. M2
    3. M1

    Reason:
    In the SomeEnd1 method, the M1 task is awaited before the M2 task has been called.

    Suggestion:
    In the SomeEnd2 method, both tasks are started before awaiting any to complete. Ideally you wouldn’t await each task individually, instead use await Task.WhenAll()… SomeEnd2 would be better like this:

    1. public async Task SomeEnd2()
    2. {
    3. var tasks = new List<Task>();
    4. tasks.Add(M1());
    5. tasks.Add(M2());
    6. await Task.WhenAll(tasks);
    7. }

    The result will be the same, but this pattern will allow you to add tasks as needed without the need to await each individually.

    Futher thoughts:
    If you needed the result of one asynchronous method before starting another method, you can kick off all non-dependent tasks and then await the task(s) need for the dependent task(s) and still await Task.WhenAll(tasks) before you need the results.

    Try the code below, I have added more output lines with some formatting that may help illustrate things a bit.

    1. CAsync2 myc = new CAsync2();
    2. await myc.SomeEnd1();
    3. Console.WriteLine();
    4. Console.WriteLine();
    5. await myc.SomeEnd2();
    6. Console.WriteLine();
    7. Console.WriteLine();
    8. await myc.SomeEnd3();
    9. public class CAsync2
    10. {
    11. public async Task<string> M1()
    12. {
    13. Console.WriteLine(" M1 start");
    14. var value = Path.GetRandomFileName();
    15. await Task.Delay(4000);
    16. Console.WriteLine(" M1 complete");
    17. return value;
    18. }
    19. public async Task M2()
    20. {
    21. Console.WriteLine(" M2 start");
    22. await Task.Delay(200);
    23. Console.WriteLine(" M2 complete");
    24. }
    25. public Task M3(string value)
    26. {
    27. Console.WriteLine(" M3 start");
    28. Console.WriteLine($" M3 - value = \"{value}\"");
    29. Console.WriteLine(" M3 complete");
    30. return Task.CompletedTask;
    31. }
    32. public async Task SomeEnd1()
    33. {
    34. Console.WriteLine("SomeEnd1 start");
    35. await M1();
    36. await M2();
    37. Console.WriteLine("SomeEnd1 complete");
    38. }
    39. public async Task SomeEnd2()
    40. {
    41. Console.WriteLine("SomeEnd2 start");
    42. var tasks = new List<Task>();
    43. tasks.Add(M1());
    44. tasks.Add(M2());
    45. await Task.WhenAll(tasks);
    46. Console.WriteLine("SomeEnd2 complete");
    47. }
    48. public async Task SomeEnd3()
    49. {
    50. Console.WriteLine("SomeEnd3 start");
    51. var tasks = new List<Task>();
    52. var m1 = M1();
    53. tasks.Add(m1);
    54. tasks.Add(M2());
    55. var m1Result = await m1;
    56. tasks.Add(M3(m1Result));
    57. await Task.WhenAll(tasks);
    58. Console.WriteLine("SomeEnd3 complete");
    59. }
    60. }

    In fact, you don’t need to add the m1 Task to the task list since we are waiting for it to be completed before startng M3.

    • 0


Most Popular Job Functions


MOST LIKED QUESTIONS