C#教科書を身につける.非同期プログラミング(async&await)
15896 ワード
1.非同期プログラミング(async&await)
https://youtu.be/PwoF8jsCUtM
01.同期と非同期
var data = DownloadData(...);
ProcessData(data);

var future = DownloadDataAsync(...);
future.ContinewWith(data => ProcessData(data));

ディナーモデリング:同期プログラミング

ディナーモデリング:非同期プログラミング(同期を含む)

ディナーモデリング:非同期プログラミング

ディナースタイル

2.プロジェクト
Tを返す
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Dinner.Common
{
public class Cooking
{
// 동기 방식의 밥 만들기 메서드
// <returns>밥</returns>
public Rice MakeRice()
{
Console.WriteLine("밥 생성중...");
Thread.Sleep(3001);
return new Rice();
}
// 비동기 방식의 밥 만들기 메서드
// <returns>밥</returns>
public async Task<Rice> MakeRiceAsync()
{
Console.WriteLine("밥 생성중...");
await Task.Delay(3001); //[A]
return new Rice();
}
// 동기 방식의 국 만들기 메서드
// <returns>국</returns>
public Soup MakeSoup()
{
Console.WriteLine("국 생성중...");
Thread.Sleep(3001);
return new Soup();
}
// 비동기 방식의 국 만들기 메서드
// <returns>국</returns>
public async Task<Soup> MakeSoupAsync()
{
Console.WriteLine("국 생성중...");
await Task.Run(() => Task.Delay(3001)); //[B]
return new Soup();
}
// 동기 방식의 달걀 만들기 메서드
// <returns>달걀</returns>
public Egg MakeEgg()
{
Console.WriteLine("달걀 생성중...");
Thread.Sleep(3001);
return new Egg();
}
// 비동기 방식의 달걀 만들기 메서드
// <returns>달걀</returns>
public async Task<Egg> MakeEggAsync()
{
Console.WriteLine("달걀 생성중...");
await Task.Delay(TimeSpan.FromMilliseconds(3001));
return await Task.FromResult<Egg>(new Egg()); //[C]
}
}
public class Rice
{
// Pass
}
public class Soup
{
// Pass
}
public class Egg
{
// Pass
}
}
using Dinner.Common;
using System;
using System.Diagnostics;
namespace Dinner.Sync
{
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
//[1] 밥 만들기
Rice rice = (new Cooking()).MakeRice(); // 스레드 차단: true
Console.WriteLine($"밥 준비 완료 - {rice.GetHashCode()}");
//[2] 국 만들기
Soup soup = (new Cooking()).MakeSoup();
Console.WriteLine($"국 준비 완료 - {soup.GetHashCode()}");
//[3] 달걀 만들기
Egg egg = (new Cooking()).MakeEgg();
Console.WriteLine($"달걀 준비 완료 - {egg.GetHashCode()}");
stopwatch.Stop();
Console.WriteLine($"\n시간: {stopwatch.ElapsedMilliseconds}밀리초");
Console.WriteLine("동기 방식으로 식사 준비 완료");
}
}
}

using Dinner.Common;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Dinner.Async
{
class Program
{
static async Task Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Rice rice = await (new Cooking()).MakeRiceAsync(); // 스레드 차단: false
Console.WriteLine($"밥 준비 완료: {rice.GetHashCode()}");
Soup soup = await (new Cooking()).MakeSoupAsync();
Console.WriteLine($"국 준비 완료: {soup.GetHashCode()}");
Egg egg = await (new Cooking()).MakeEggAsync();
Console.WriteLine($"달걀 준비 완료: {egg.GetHashCode()}");
stopwatch.Stop();
Console.WriteLine($"\n시간: {stopwatch.ElapsedMilliseconds}밀리초");
Console.WriteLine("비동기 방식으로 식사 준비 완료");
}
}
}

using System;
using static System.Console;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Dinner.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Dinner
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("[?] 어떤 방식으로 실행할까요? (0~4 번호 입력)\n" +
"0. 동기\t\t1. await\t2. Task<T>\t3. WhenAll\t4. WhenAny ");
var number = Convert.ToInt32(Console.ReadLine());
switch (number)
{
case 1: // 비동기(동기 프로그램을 포함한)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Egg egg = await (new Cooking()).MakeEggAsync();
Console.WriteLine($"달걀 재료 준비 완료: {egg.GetHashCode()}");
Rice rice = await (new Cooking()).MakeRiceAsync();
Console.WriteLine($"김밥 준비 완료: {rice.GetHashCode()}");
Soup soup = await (new Cooking()).MakeSoupAsync();
Console.WriteLine($"국 준비 완료: {soup.GetHashCode()}");
stopwatch.Stop();
Console.WriteLine($"\n시간: {stopwatch.ElapsedMilliseconds}");
Console.WriteLine("비동기 방식으로 식사(김밥) 준비 완료");
}
break;
case 2: // 비동기(함께 실행)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
// 3개의 Async 메서드가 동시 실행
Task<Rice> riceTask = (new Cooking()).MakeRiceAsync();
Task<Soup> soupTask = (new Cooking()).MakeSoupAsync();
Task<Egg> eggTask = (new Cooking()).MakeEggAsync();
Rice rice = await riceTask;
Console.WriteLine($"식탁에 밥 준비 완료: {rice.GetHashCode()}");
Soup soup = await soupTask;
Console.WriteLine($"식탁에 국 준비 완료: {soup.GetHashCode()}");
Egg egg = await eggTask;
Console.WriteLine($"식탁에 달걀 준비 완료: {egg.GetHashCode()}");
stopwatch.Stop();
Console.WriteLine($"\n시간: {stopwatch.ElapsedMilliseconds}");
Console.WriteLine("비동기 방식으로 식사 준비 완료");
}
break;
case 3: // 비동기(모두 완료되는 시점)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
// 3개의 Async 메서드가 동시 실행
Task<Rice> riceTask = (new Cooking()).MakeRiceAsync();
Task<Soup> soupTask = (new Cooking()).MakeSoupAsync();
Task<Egg> eggTask = (new Cooking()).MakeEggAsync();
// 모든 작업이 다 완료될 때까지 대기
await Task.WhenAll(riceTask, soupTask, eggTask);
Console.WriteLine("식탁에 모든 식사 준비 완료");
stopwatch.Stop();
Console.WriteLine($"\n시간: {stopwatch.ElapsedMilliseconds}");
Console.WriteLine("비동기 방식으로 식사 준비 완료");
}
break;
case 4:
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
// 3개의 Async 메서드가 동시 실행
Task<Rice> rTask = (new Cooking()).MakeRiceAsync();
Task<Soup> sTask = (new Cooking()).MakeSoupAsync();
Task<Egg> eTask = (new Cooking()).MakeEggAsync();
// 하나라도 작업이 끝나면 확인
var allTasks = new List<Task> { rTask, sTask, eTask };
while (allTasks.Any()) // 작업이 하나라도 있으면 실행
{
Task finished = await Task.WhenAny(allTasks);
if (finished == rTask)
{
Rice rice = await rTask;
Console.WriteLine($"밥 준비 완료 - {rice}");
}
else if (finished == sTask)
{
Soup soup = await sTask;
Console.WriteLine($"국 준비 완료 - {soup}");
}
else
{
Egg egg = await eTask;
Console.WriteLine($"달걀 준비 완료 - {egg}");
}
allTasks.Remove(finished); // 끝난 작업은 리스트에서 제거
}
stopwatch.Stop();
Console.WriteLine(
$"\n시간: {stopwatch.ElapsedMilliseconds}");
Console.WriteLine("비동기 방식으로 식사 준비 완료");
}
break;
default: // 동기(Sync)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
//[1] 밥 만들기
Rice rice = (new Cooking()).MakeRice(); // 스레드 차단: true
Console.WriteLine($"밥 준비 완료 - {rice.GetHashCode()}");
//[2] 국 만들기
Soup soup = (new Cooking()).MakeSoup();
Console.WriteLine($"국 준비 완료 - {soup.GetHashCode()}");
//[3] 달걀 만들기
Egg egg = (new Cooking()).MakeEgg();
Console.WriteLine($"달걀 준비 완료 - {egg.GetHashCode()}");
stopwatch.Stop();
Console.WriteLine($"\n시간: {stopwatch.ElapsedMilliseconds}");
Console.WriteLine("동기 방식으로 식사 준비 완료");
}
break;
}
}
}
}

Reference
この問題について(C#教科書を身につける.非同期プログラミング(async&await)), 我々は、より多くの情報をここで見つけました https://velog.io/@ansalstmd/C교과서-마스터하기-44.-비동기-프로그래밍asyncawaitテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol