ํฌ์ŠคํŠธ

๐ŸŒ’ C# Thread/Task

๐Ÿ’ซ lock


1
2
3
4
5
private readonly object thisLock = new object();
lock (thisLock)
{
	// Bla Bla
}

์ž„๊ณ„ ์˜์—ญ (Critical Section)์„ ๋งŒ๋“ค์–ด์ฃผ๋Š” ํ‚ค์›Œ๋“œ
Thread๋Š” lock์„ ์–ป์–ด์•ผ Critical Secion์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์™ธ๋ถ€ ์ฝ”๋“œ์—์„œ๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” this, Type ํ˜•์‹ (typeof, GetType()), string ํ˜•์‹์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜์ง€ ๋ง ๊ฒƒ.

@ Key, ์ „์šฉ ๊ฐœ์ฒด ์ธ์Šคํ„ด์Šค
@ Critical Section, ํ•œ ๋ฒˆ์— ํ•œ ์Šค๋ ˆ๋“œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ ์˜์—ญ

๐Ÿ’ซ ์Šค๋ ˆ๋“œ


๋ฉ”๋ชจ๋ฆฌ ๊ฐ€์ƒํ™”
๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์—†๋Š”๋ฐ ์žˆ๋Š”์ฒ™ ํ•˜๋Š”๊ฒƒ
๋””์Šคํฌ๋ฅผ ์จ์„œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ ์€๋ฐ ๋งŽ์€์ฒ™ ํ•˜๋Š”๊ฒƒ

CPU ๊ฐ€์ƒํ™”
CPU๊ฐ€ ์—†๋Š”๋ฐ ์žˆ๋Š”์ฒ™ ํ•˜๋Š”๊ฒƒ

์œˆ๋„์šฐ95 ์ด์ „
์œˆ๋„์šฐ OS์— ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜๋ฐ–์— ์—†์—ˆ์Œ
ํ”„๋กœ๊ทธ๋žจ ํ•˜๋‚˜๊ฐ€ ๋ฌดํ•œ๋ฃจํ”„์—๋น ์ง€๋งŒ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ๋„ ๋ฉˆ์ถค
CPU๋ฅผ ๋‚˜๋ˆ ์จ์•ผ ํ•˜๋Š”๋ฐ ํ•˜๋‚˜๋ฐ–์— ์—†์–ด์„œ ๊ทธ๋Ÿฌ์ง€ ๋ชปํ•จ
ํ•œ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฌดํ•œ๋ฃจํ”„๋ฅผ ๋Œ๋ฉด ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ์—๋„ ์˜ํ–ฅ

๊ทธ๋ž˜์„œ CPU ๊ฐ€์ƒํ™”
์ด์ œ CPU๋ฅผ ์“ฐ์ง€ ๋ง๊ณ  ์Šค๋ ˆ๋“œ ์จ
์Šค๋ ˆ๋“œ๋ฅผ CPU์ฒ˜๋Ÿผ ์จ

ํ”„๋กœ์„ธ์Šค์—๊ฒŒ ์Šค๋ ˆ๋“œ๋ฅผ ๋‚˜๋ˆ ์ฃผ๊ณ 
๊ทธ ์Šค๋ ˆ๋“œ๊ฐ€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž…์žฅ์—์„œ๋Š” ๋งˆ์น˜ CPU์ธ๊ฒƒ์ฒ˜๋Ÿผ ์‚ฌ์šฉ

์ด์ œ ์—ฌ๋Ÿฌ ๊ฐœ๋‹ˆ๊นŒ, ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฌดํ•œ๋ฃจํ”„์— ๋น ์ ธ๋„ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋Š” ๋ฉˆ์ถ”์ง€ ์•Š์Œ
๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋Š” ์ž์‹ ์—๊ฒŒ ์ฃผ์–ด์ง„ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉ

๐Ÿซง ์Šค๋ ˆ๋“œ๋Š” ๊ฐ€๋ฒผ์šด ์ž์›์ธ๊ฐ€?

์ƒ๋Œ€์ ์œผ๋กœ ํ”„๋กœ์„ธ์Šค๋ณด๋‹ค ๊ฐ€๋ณ์ง€๋งŒ,
์ ˆ๋Œ€์ ์œผ๋กœ ๋ฌด๊ฑฐ์šด ๋ฆฌ์†Œ์Šค์ด๋‹ค.

  • ๊ณต๊ฐ„๋น„์šฉ
    • Thread Kernel Object
      • x86 : 700B
      • x64 : 1240B
      • ARM : 350B
    • Thread Environment Block : 4K
    • User Mode stack : 1MB
    • Kernel Mode stack
      • 32bit OS : 12KB
      • 64bit OS : 24KB
    • ์ด : 1053KB ๋‚จ์ง“
  • ์‹œ๊ฐ„๋น„์šฉ
    • DLL Thread attach/detach notification
      • ํ”„๋กœ์„ธ์Šค์— ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์งˆ๋•Œ๋งˆ๋‹ค, ๊ฐ DLL์˜ main ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ
      • ๋ฌธ์•ˆ์ธ์‚ฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด์ง€์š”, ์Šค๋ ˆ๋“œ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์กŒ์–ด์š”
      • DLL์€ ์Šค๋ ˆ๋“œ๋ฅผ ์œ„ํ•œ ๊ณต๊ฐ„์„ ๋งˆ๋ จ
      • ๋Œ€ํ‘œ์ ์ธ๊ฒŒ C Runtime Library (DLL)
    • Context Switching
      • ์ด ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ–๊ณ  ์žˆ๋˜ ๊ฐ€์ƒ์˜ CPU ์ •๋ณด๋“ค์„ ๋กœ๋“œํ•ด์„œ ์ˆ˜ํ–‰ํ•˜๊ณ 
      • ์ผ์ • ์‹œ๊ฐ„ (Quantum)์ด ์ง€๋‚˜๋ฉด ๋‹ค์‹œ ์ €์žฅํ•˜๊ณ 
      • ๋‹ค์Œ ์Šค๋ ˆ๋“œ๋ฅผ ๋กœ๋“œโ€ฆ
    • -> DLL์ด ๋งŽ์œผ๋ฉด ๋งŽ์„์ˆ˜๋ก, ์Šค๋ ˆ๋“œ๊ฐ€ ๋งŽ์œผ๋ฉด ๋งŽ์„์ˆ˜๋ก

๐Ÿซง ์ด์ œ ๊ทธ๋งŒ ํ•ด์•ผ ํ•  ๋ฐ”๋ณด์ง“

์ž‘์—…๊ด€๋ฆฌ์ž

๐Ÿซง ๋ช…์‹œ์ ์œผ๋กœ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ง๋ผ

  • ์˜ˆ์™ธ
    • ๋ณดํ†ต ๋‹จ๊ณ„์˜ ์Šค๋ ˆ๋“œ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ์•„๋‹Œ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ
    • ํฌ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ
    • ๊ณ„์‚ฐ ์ค‘์‹ฌ์˜ ์ž‘์—…์ด ์ƒ๋‹นํžˆ ์˜ค๋žซ๋™์•ˆ ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

๊ฐ€๋Šฅํ•œ Thread class๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ง ๊ฒƒ

๐Ÿซง ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

  • ์‘๋‹ต์„ฑ์˜ ๊ฐœ์„ 
    • ํด๋ผ์ด์–ธํŠธ ์ธก UI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜
    • UI ์Šค๋ ˆ๋“œ
    • ์ž‘์—… ์Šค๋ ˆ๋“œ์˜ ๊ฐœ์ˆ˜๋Š” ๋Š˜์–ด๋‚˜์ง€๋งŒ, ์‘๋‹ต์„ฑ์ด ๊ฐœ์„ ๋˜๋ฏ€๋กœ ์ „์ฒด์ ์œผ๋กœ ์ข€ ๋” ๋‚˜์€ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ํŒ๋‹จ
  • ์„ฑ๋Šฅ
    • ํด๋ผ์ด์–ธํŠธ, ์„œ๋ฒ„ ์ธก Application
    • ๋‹ค์ค‘ CPUI์— ํ•œํ•ด์„œ ์„ฑ๋Šฅ ๊ฐœ์„ 
  • ์Šค๋ ˆ๋“œ๋ฅผ ๊ฐ€์žฅ ์ž˜ ํ™”์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
    • ์Šค๋ ˆ๋“œ ํ’€์„ ์ด์šฉํ•˜๊ณ  ๋น„๋™๊ธฐ๋กœ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ผ
    • -> ์šฐ๋ฆฌ๊ฐ€ TASK ๋ณ‘๋ ฌํ™”๋ฅผ ์•Œ์•„์•ผ ํ•˜๋Š” ์ด์œ 

๐Ÿซง ๊ณ„์‚ฐ ์ค‘์‹ฌ ๋น„๋™๊ธฐ ์ž‘์—…

  • CLR ์Šค๋ ˆ๋“œ ํ’€
    • ์‚ฌ์‹ค ์ด๋ฏธ ๋งŒ๋“ค์–ด์ ธ ์žˆ์Œ
    • ๋ช…์‹œ์ ์œผ๋กœ ์“ฐ์ง€์•Š๊ณ  ์žˆ์—ˆ์„ ๋ฟ
    • Requests Queue์— ์ž‘์—…์ด ๋“ค์–ด์˜ค๋ฉด, ๊ทธ๋•Œ ์Šค๋ ˆ๋“œ๋ฅผ ํ• ๋‹น
    • ์ตœ๋Œ€ํ•œ ํ•˜๋‚˜๋งŒ ์“ฐ๋ ค๊ณ ํ•จ
      • ๋งŽ์ด ๋“ค์–ด์˜ค๋ฉด, ์ฝ”์–ด ์ˆ˜๋งŒํผ๋งŒ ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉ
    • Request Queue์— ์ž‘์—…์ด ์ผ์ •์‹œ๊ฐ„ ๋“ค์–ด์˜ค์ง€ ์•Š์œผ๋ฉด ์Šค๋ ˆ๋“œ๋ฅผ ์ œ๊ฑฐ
      • ์ƒ์„ฑ/์ œ๊ฑฐ ๋น„์šฉ ์ตœ์†Œํ™”

๐Ÿซง QueueUserWorkItem

1
public static bool QueueUserWorkItem(WaitCallback callBack, object state);
1
2
3
4
5
6
7
8
9
for (int i = 0; i < 100; i++)
{
	ThreadPool.QueueUserWorkItem((obj) =>
	{
		Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
	});
}

Console.ReadLine();
  • ์ž‘์—… ์™„๋ฃŒ ์‹œ์ ์„ ์•Œ ์ˆ˜ ์—†์Œ
  • ์ž‘์—… ์ˆ˜ํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์–ป์–ด ์˜ฌ ์ˆ˜ ์—†์Œ
  • ์ทจ์†Œ / ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ถˆ๊ฐ€๋Šฅ
  • -> ์“ฐ๊ธฐ ์‰ฝ์ง€๋งŒ ์ด๋Ÿฐ ํ•œ๊ณ„๋“ค ๋•Œ๋ฌธ์— ์ž˜ ์•ˆ์”€

๐Ÿซง Task

Task ๋‚˜๋ˆ„๋ฉด ์žฅ์ ‘
Taks ๊ฐ„์˜ ์ƒ๊ด€๊ด€๊ณ„๊ฐ€ ์—†๋‹ค๋ฉด, ๋ณ‘๋ ฌ๋กœ ์ˆ˜ํ–‰ ๊ฐ€๋Šฅ -> ๋นจ๋ผ์ง„๋‹ค

1
2
3
4
5
6
7
8
9
10
// QueueUserWorkItem๊ณผ ์œ ์‚ฌ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝ”๋“œ ํŒจํ„ด
Action action = () =>
{
	Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
};

Task task = new Task(action); // #1: Task ๊ฐ์ฒด ์ƒ์„ฑ ํ›„
task.Start(); // Start ๋ช…์‹œ์  ํ˜ธ์ถœ

Task.Run(action); // #2: Task.Run์„ ์ด์šฉํ•˜์—ฌ ์ž‘์—… ์ˆ˜ํ–‰
1
2
3
4
5
6
// ๊ฒฐ๊ณผ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” Task ๊ฐ์ฒด ์ƒ์„ฑ, Sum ํ˜ธ์ถœ ์‹œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด?
Task<int> task = new Task<int>((n) => Sum((int)n), 100);
t.Start(); // ๋ช…์‹œ์  ์ˆ˜ํ–‰
t.Wait(); // Task ์™„๋ฃŒ ๋Œ€๊ธฐ (์™„๋ฃŒ ์‹œ์ ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค)

Console.WrtieLine(t.Result); // t.Result ๊ฒฐ๊ณผ ํš๋“ (๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค)

Canceling a Task

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
private static int Sum(CancellationToken ct, int n)
{
	int sum = 0;
	for (; n > 0; n--)
	{
		// ์ž‘์—… ์ทจ์†Œ๊ฐ€ ์š”์ฒญ๋˜๋ฉด OperationCanceledException์„
		// innerException์œผ๋กœ ๊ฐ–๋Š” AggregateException์„ ๋˜์ง
		ct.ThrowIfCancellationRequested();
		checked
		{
			sum += n;
		}
	}
	return sum;
}

static void Main(string[] args)
{
	CancellationTokenSource cts = new CancellationTokenSource();
	Task<Int32> t = Task.Run(() => Sum(cts.Token, 100000000), cts.Token);
	cts.Cancel(); // ์ž‘์—… ์ทจ์†Œ ์š”์ฒญ

	try
	{
		Console.WriteLine("The result is: " + t.Result);
	}
	catch (AggregateException e)
	{
		e.Handle((innerException) => innerException is OperationCanceledException);
		// Operation.. ์ด๋ฉด ์ฒ˜๋ฆฌ๋œ ๊ฒƒ์œผ๋กœ  

		Console.WriteLine("Exception: " + e.InnerExceptions[0].Message);
	}
}
  • ์ž‘์—… ์™„๋ฃŒ ์‹œ์ ์„ ์•Œ ์ˆ˜ ์žˆ์Œ
  • ์ž‘์—… ์ˆ˜ํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์–ป์–ด ์˜ฌ ์ˆ˜ ์žˆ์Œ
  • ์ทจ์†Œ / ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

๐Ÿซง Task ์—ฐ๊ฒฐ1

1
2
3
4
5
6
// ์›จ์ดํŒ… ์•„ํ‚คํ…์ฒ˜
Task<int> task = new Task<int>((n) => Sum((int)n), 100);
t.Start();
t.Wait(); // ๋Œ€๊ธฐ

Console.WrtieLine(t.Result);

to

1
2
3
4
5
6
7
8
9
10
11
// waitfree, lockfree ์•„ํ‚คํ…์ฒ˜ (์„œ๋ฒ„์—์„œ ๋งŽ์ด ์‚ฌ์šฉ)

// t Task๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด cwt Task๋ฅผ ์ˆ˜ํ–‰
Task<Int32> t = Task.Run(() => Sum(CancellationTokenSource.None, 100));
Task cwt = t.ContinueWith( // ์™„๋ฃŒ๋˜๋ฉด
(antecedent) =>
{
	Console.WriteLine("The result is: " + antecedent.Result);
});

// ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฐ”๋กœ ๋น ์ ธ๋‚˜์˜ด


๐Ÿซง Task ์—ฐ๊ฒฐ2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// TaskContinuationOptions
// OnlyOnCanceled, OnlyOnFaulted, OnlyOnRanToCompletion ๊ทธ์™ธ ๊ธฐํƒ€ ๋“ฑ๋“ฑ

CancellationTokeSource cts = new CancellationTokenSource();
cts.Cancel();

Task<Int32> t = Task.Run(() => Sum(cts.Token, 100000000), cts.Token);

t.ContinueWith((task) => // ์„ฑ๊ณต ์™„๋ฃŒ์‹œ
{
	Console.WriteLine("The result is: " + task.Result);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
t.ContinueWith((task) => // ์‹คํŒจ/์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ
{
	Console.WriteLine("The task failed" + task.Exception.InnerException);
}, TaskContinuationOptions.OnlyOnFaulted);
t.ContinueWith((task) => // ์ทจ์†Œ์‹œ
{
	Console.WriteLine("The task was canceled");
}, TaskContinuationOptions.OnlyOnCanceled);


๐Ÿซง Task ์—ฐ๊ฒฐ3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Parent-Child Task๋กœ์˜ ์—ฐ๊ฒฐ, TaskCreationOptions.AttachedToParent
Task<Int32[]> parent = new Task<Int32[]>(() =>
{
	var results = new Int32[3];
	new Task(() => results[0] = Sum(CancellationToken.None, 10000), TaskCreationOptions.AttachedToParent).Start();
	new Task(() => results[1] = Sum(CancellationToken.None, 20000), TaskCreationOptions.AttachedToParent).Start();
	new Task(() => results[2] = Sum(CancellationToken.None, 30000), TaskCreationOptions.AttachedToParent).Start();
	return results;
});

// Child Task๋“ค์ด ๋ชจ๋‘ ์™„๋ฃŒ๋˜๋ฉด = parent๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด

var cwt = parent.ContinueWith((parentTask) => // parentTask๊ฐ€ ๋๋‚˜๋ฉด ์ˆ˜ํ–‰ํ•  Task ์—ฐ๊ฒฐ
{
	Array.ForEach(parentTask.Result, Console.WriteLine);
});

parent.Start();


๐Ÿซง I/O ์ค‘์‹ฌ์˜ ๋น„๋™๊ธฐ ์ž‘์—…

๐Ÿซง ๋™๊ธฐ I/O ๋งค์ปค๋‹ˆ์ฆ˜

๐Ÿซง ๋น„๋™๊ธฐ I/O ๋งค์ปค๋‹ˆ์ฆ˜

  • ๋น„๋™๊ธฐ
    • ์ž‘์—…์„ ํ•˜๋Š” ์ฃผ์ฒด์™€ ์ž‘์—…์„ ์š”์ฒญํ•˜๋Š” ์ฃผ์ฒด๊ฐ€ ๋‹ค๋ฆ„
    • ์ž‘์—…์„ ํ•˜๋Š” ์ฃผ์ฒด๊ฐ€ ์ž‘์—…์„ ์š”์ฒญํ•˜๋Š” ์ฃผ์ฒด์—๊ฒŒ ์•Œ๋ ค์ฃผ๋Š” ๋ฐฉ์‹
      • (H/W๊ฐ€ ์™„๋ฃŒํ•˜๋ฉด ์Šค๋ ˆ๋“œ์—๊ฒŒ ๋…ธํ‹ฐํ”ผ์ผ€์ด์…˜์„ ์คŒ)

์ด๋ฅผ ์–ด๋–ป๊ฒŒ ํŒจํ„ดํ™”ํ•˜๋Š๋ƒ?

๐Ÿซง Comparing Patterns

  • Sync
1
2
public int Read(byte[] buffer, int offset, int count);
// ๊ทผ๋ฐ ๋น„๋™๊ธฐ๊ฐ€ ์ข‹์ž–์•„?
  • APM (Asynchronous Programming Model)
1
2
3
4
5
6
public IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state);
public int EndRead(IAsyncResult asyncResult);
// ๋น„๋™๊ธฐ : ์‹œํ‚ค๋Š” ๋ฐฉ์‹๊ณผ ๊ฒฐ๊ณผ๋ฅผ ์ทจํ•˜๋Š” ๋ฐฉ์‹์ด ๋‹ค๋ฆ„
// ๋ฌธ์ œ : ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ์•„์ง, ๋ฐ›์„ ๋•Œ๋„ ๋ณต์žกํ•˜๊ณ , EndRead๋ฅผ ์–ธ์ œ ํ˜ธ์ถœํ•ด์•ผ ํ• ์ง€ ์• ๋งคํ•จ

// ์ข€ ๋” ์‰ฌ์šด ๋ฐฉ๋ฒ•?
  • EAP (Event-based Asynchronous Pattern)
1
2
3
4
5
6
public void ReadAsync(byte[] buffer, int offset, int count);
public event ReadCompletedEventHandler ReadCompleted;

// ๊ฒฐ๊ณผ๋ฅผ ์ทจํ•˜๋Š” ๋ฐฉ์‹์„ ์ด๋ฒคํŠธ๋กœ
// ๋ฌธ์ œ : APM, EAP ๋‘˜ ๋‹ค ์ž‘์—…์„ ์‹œํ‚ค๋Š” ์œ„์น˜์™€ ๋ฐ›๋Š” ์œ„์น˜๊ฐ€ ๋‹ค๋ฆ„
// (ํ˜ธ์ถœํ•˜๋Š” ์ชฝ๊ณผ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜(์ฝœ๋ฐฑ) ์‚ฌ์ด์— ์ปจํ…์ŠคํŠธ๋ฅผ ๋„˜๊ธฐ๊ธฐ ์œ„ํ•ด ์ง€์—ญ๋ณ€์ˆ˜๋‚˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ๋„˜๊ฒจ์•ผ ํ•จ)
  • TAP (Task-based Asynchronous Pattern)
1
public Task<int> ReadAsync(byte[] buffer, int offset, int count);

Sync, TAP ๊ฐ„์˜ ๋ฉ”์„œ๋“œ ์›ํ˜•์ด ๊ฐ€์žฅ ์œ ์‚ฌํ•จ.
-> ๊ฐ€์žฅ ์ง๊ด€์ ์ด๊ณ , Sync ๋ฐฉ์‹๊ณผ ๋‹ฎ์•„ ์žˆ์–ด ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด ๋น„๋™๊ธฐ ํŒจํ„ด

๐Ÿซง Async/Await

๋‚ด๋ถ€ ๋™์ž‘
async ๋ฉ”์„œ๋“œ๋Š” Task๋ฅผ ๋ฐ˜ํ™˜
await ํ‚ค์›Œ๋“œ๋Š” Task๋ฅผ ๋ฐ›์•„์„œ Task๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
await ํ‚ค์›Œ๋“œ๋Š” Task๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด Task์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜

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
// ์‹ค์ˆ˜ ์กฐ์‹ฌ !!
// ์ด๊ฑด ํ•จ์ˆ˜๊ฐ€ ์ฒด์ธ๋˜์–ด ์žˆ์–ด์„œ, ์ฒซ๋ฒˆ์งธ ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜์•ผ ๋‘๋ฒˆ์งธ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋จ
await SomeMethodAsync();
await SomeMethodAsync();

// ConfigureAwait(false)๋ฅผ ์“ฐ๋ฉด ์ฒซ๋ฒˆ์งธ ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๊ธฐ ์ „์— ๋‘๋ฒˆ์งธ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋จ
await SomeMethodAsync().ConfigureAwait(false);
await SomeMethodAsync().ConfigureAwait(false);

// ์•„๋‹ˆ๋ฉด Task๋ฅผ ๋จผ์ € ๋ฐ›์•„์„œ, ๊ทธ๊ฑธ await
Task t = SomeMethodAsync();
Task t2 = SomeMethodAsync();
await t;
await t2;

// WhenAll์„ ์“ธ ์ˆ˜๋„ ์žˆ์Œ
await Task.WhenAll(t, t2);

// WhenAny๋ฅผ ์“ธ ์ˆ˜๋„ ์žˆ์Œ
var tasks = new List<Task>() { t, t2 };
while (tasks.Count > 0)
{
	Task t = await Task.WhenAny(tasks);
	tasks.Remove(t);
}

๐Ÿ’ซ Ref

์ฐธ๊ณ  : โ€˜C#์„ ์ด์šฉํ•œ Task ๋ณ‘๋ ฌํ™”์™€ ๋น„๋™๊ธฐ ํŒจํ„ดโ€™
์ฐธ๊ณ  : โ€˜C# ๋น„๋™๊ธฐ ์‚ฌ์šฉ ์˜ˆ์ œ(Task, WhenAll, WhenAny)โ€™
์ฐธ๊ณ  : โ€˜C# ๋น„๋™๊ธฐ/๋Œ€๊ธฐ/์ž‘์—… ์„ค๋ช…(์‹ฌ์ธต ๋ถ„์„)โ€™

๋ฐ‘ ๋‹จ๊ณ„๋Š” ๋˜‘๊ฐ™์ง€๋งŒ
์กฐ๊ธˆ ์ถ”์ƒํ™”ํ•ด๋ณด๋ฉด
์Šค๋ ˆ๋“œ๋Š” ํฌ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์™€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋กœ ๋‚˜๋‰จ
ํฌ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š์œผ๋ฉด ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š์Œ
๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ์ข…๋ฃŒ๋จ

Delegate : ๋‚ด๋ถ€์ ์œผ๋กœ ์˜ค๋ธŒ์ ํŒ…์„ ํ•ฉ๋‹ˆ๋‹ค๋งŒ, ์˜ค๋ธŒ์ ํŠธ์•ˆ์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜์— ๊ด€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํƒ€์ž…

๋น„ํŠธ๋ ˆ๋ฒจ parallel
๋ฐ์ดํ„ฐ parallel
task parallel

Task.Delay(1000); Task.Run(() => { });

async ํ‚ค์›Œ๋“œ๋ฅผ ์“ฐ๋ฉด
ํ•จ์ˆ˜๊ฐ€ ์ƒํƒœ๋จธ์‹ ์œผ๋กœ ๋ณ€ํ™˜๋จ

์ƒํƒœ๋จธ์‹ ์€ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ , ๋‹ค์‹œ ์‹คํ–‰๋  ๋•Œ ์ƒํƒœ๋ฅผ ๋ณต์›ํ•˜๋Š” ๊ฒƒ

๐Ÿ’ซ ๋™๊ธฐ/๋น„๋™๊ธฐ


๐Ÿซง ๋™๊ธฐ

Synchrounous

๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ์ดํ›„, ๋ฉ”์†Œ๋“œ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์ฝ”๋“œ ์‹คํ–‰์ด ์ฐจ๋‹จ๋จ
์ฆ‰, ์ž‘์—…์€ ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰๋˜๋ฏ€๋กœ ํ•˜๋‚˜์˜ ์ž‘์—…์ด ๋๋‚˜์•ผ ๋‹ค์Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ

๐Ÿซง ๋น„๋™๊ธฐ

Asynchronous

๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ์ดํ›„ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š์•„๋„ ์ฝ”๋“œ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค์Œ ์ฝ”๋“œ ์‹คํ–‰
๋น„๋™๊ธฐ ๋ฉ”์„œ๋“œ๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ ์ˆ˜ํ–‰๋˜๋ฏ€๋กœ, ๋ฉ”์ธ์Šค๋ ˆ๋“œ๋Š” ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ

์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.