C#을 이용한 task 병렬화와 비동기 패턴

30
C#을 이용한 Task 병렬화와 비동기 패턴 -한국마이크로소프트 에반젤리스트 김명신 부장 12월의 주제 C#완벽분석, 원샷 올킬!

Transcript of C#을 이용한 task 병렬화와 비동기 패턴

Page 1: C#을 이용한 task 병렬화와 비동기 패턴

C#을 이용한 Task 병렬화와 비동기 패턴-한국마이크로소프트 에반젤리스트 김명신 부장

12월의 주제

C#완벽분석, 원샷 올킬!

Page 2: C#을 이용한 task 병렬화와 비동기 패턴
Page 3: C#을 이용한 task 병렬화와 비동기 패턴
Page 4: C#을 이용한 task 병렬화와 비동기 패턴

• DLL Thread attach/detach notification

• Context Switching

대략 1053KB 남짓DLL이많으면많을수록,

스레드가많으면많을수록

Page 5: C#을 이용한 task 병렬화와 비동기 패턴
Page 6: C#을 이용한 task 병렬화와 비동기 패턴
Page 7: C#을 이용한 task 병렬화와 비동기 패턴

우리가 TASK 병렬화를알아야하는이유

Page 8: C#을 이용한 task 병렬화와 비동기 패턴
Page 9: C#을 이용한 task 병렬화와 비동기 패턴
Page 10: C#을 이용한 task 병렬화와 비동기 패턴

Thread pool

Requests Queue

Page 11: C#을 이용한 task 병렬화와 비동기 패턴

public static bool QueueUserWorkItem(

WaitCallback callBack,

Object state

)

for (int i = 0; i < 100; ++i){

ThreadPool.QueueUserWorkItem((obj) => Console.WriteLine(Thread.CurrentThread.ManagedThreadId));

}

Console.ReadLine();

Page 12: C#을 이용한 task 병렬화와 비동기 패턴

// QueueUserWorkItem과 유사 동작을 수행하는 코드 패턴

Action action = new Action(() => Console.WriteLine(Thread.CurrentThread.ManagedThreadId));

Task t = new Task(action); // #1: Task 객체 생성 후t.Start(); // Start() 명시적 호출

Task.Run(action); // #2: Task.Run을 이용하여 작업 수행

// 결과 값을 가져오는 Task 객체 생성, Sun() 호출시 예외가 발생한다면 ?

Task<int> t = new Task<int>(n => Sum((int)n), 100);t.Start(); // 명시적 수행t.Wait(); // Task 완료 대기

Console.WriteLine("The Sum is: " + t.Result); // t.Result 결과 획득

Page 13: C#을 이용한 task 병렬화와 비동기 패턴

private static int Sum(CancellationToken ct, int n) {int sum = 0;for (; n > 0; n--) {

// 작업 취소가 요청되면 OperationCanceledException을// innerExceptions로 하는 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, 10000000), cts.Token);cts.Cancel(); // 작업 취소try {

Console.WriteLine("The sum is: " + t.Result);} catch (AggregateException x) { // AggregateException exception handler

x.Handle(e => e is OperationCanceledException); // Operation… 이면 처리된 것으로Console.WriteLine("Sum was canceled");

}}

Page 14: C#을 이용한 task 병렬화와 비동기 패턴

// t Task가 완료되면 cwt Task를 수행한다.

Task<Int32> t = Task.Run(() => Sum(CancellationToken.None, 100));

Task cwt = t.ContinueWith(task => Console.WriteLine("The sum is: " + task.Result));

// 결과 값을 가져오는 Task 객체 생성, Sun() 호출시 예외가 발생한다면 ?

Task<int> t = new Task<int>(n => Sum((int)n), 100);t.Start(); // 명시적 수행t.Wait(); // Task 완료 대기

Console.WriteLine("The Sum is: " + t.Result); // t.Result 결과 획득

Page 15: C#을 이용한 task 병렬화와 비동기 패턴

// TaskContinuationOptions// OnlyOnCanceled, OnlyOnFaulted, OnlyOnRantoCompletion, 그외 기타 등등

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

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

t.ContinueWith( // 성공 완료시task => Console.WriteLine("The sum is: " + task.Result),TaskContinuationOptions.OnlyOnRanToCompletion);

t.ContinueWith( // 예외 발생시task => Console.WriteLine("Sum threw: "+task.Exception.InnerException),TaskContinuationOptions.OnlyOnFaulted);

t.ContinueWith(

task => Console.WriteLine("Sum was canceled"), TaskContinuationOptions.OnlyOnCanceled);

Page 16: C#을 이용한 task 병렬화와 비동기 패턴

// Parent/Child Task로의 연결, TaskCreationOptions.AttachedToParentTask<Int32[]> parent = new Task<Int32[]>(() =>{

var results = new Int32[3]; new Task(() => // 차일드로 연결

results[0] = Sum(10), TaskCreationOptions.AttachedToParent).Start();new Task(() => // 차일드로 연결

results[1] = Sum(20), TaskCreationOptions.AttachedToParent).Start();new Task(() => // 차일드로 연결

results[2] = Sum(30), TaskCreationOptions.AttachedToParent).Start();return results;

});

var cwt = parent.ContinueWith( // parent Task가 끝나면 수행할 Task 연결parentTask => Array.ForEach(parentTask.Result, Console.WriteLine));

parent.Start();

Page 17: C#을 이용한 task 병렬화와 비동기 패턴

intint int

int []

60초

30초

Page 18: C#을 이용한 task 병렬화와 비동기 패턴
Page 19: C#을 이용한 task 병렬화와 비동기 패턴
Page 20: C#을 이용한 task 병렬화와 비동기 패턴
Page 21: C#을 이용한 task 병렬화와 비동기 패턴

public class MyClass

{

public int Read(byte [] buffer, int offset, int count);

}

public class MyClass

{

public IAsyncResult BeginRead(

byte [] buffer, int offset, int count,

AsyncCallback callback, object state);

public int EndRead(IAsyncResult asyncResult);

}

public class MyClass

{

public void ReadAsync(byte [] buffer, int offset, int count);

public event ReadCompletedEventHandler ReadCompleted;

}

public class MyClass

{

public Task<int> ReadAsync(byte [] buffer, int offset, int count);

}

1. Sync

2. APM

3. EAP

4. TAP

Page 22: C#을 이용한 task 병렬화와 비동기 패턴

private void Button_Click(object sender, RoutedEventArgs e)

{

string url = "http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx";

WebClient client = new WebClient();

client.DownloadStringCompleted += client_DownloadStringCompleted;

client.DownloadStringAsync(new Uri(url));

}

void client_DownloadStringCompleted(object sender,

DownloadStringCompletedEventArgs arg)

{

Debug.WriteLine(arg.Result);

}

Page 23: C#을 이용한 task 병렬화와 비동기 패턴

private void Button_Click(object sender, RoutedEventArgs e)

{

string url = "http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx";

WebClient client = new WebClient();

client.DownloadStringCompleted +=

(s, arg) => Debug.WriteLine(arg.Result);

client.DownloadStringAsync(new Uri(url));

}

Page 24: C#을 이용한 task 병렬화와 비동기 패턴

private void Button_Click(object sender, RoutedEventArgs e)

{

string url = "http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx";

WebClient client = new WebClient();

Task<string> t = client.DownloadStringTaskAsync(new Uri(url));

t.Wait();// 작업이 완료되때까지 대기

Debug.WriteLine(t.Result);

}

Page 25: C#을 이용한 task 병렬화와 비동기 패턴

private void Button_Click(object sender, RoutedEventArgs e)

{

Task.Run(() => WorkAsync());

}

private void WorkAsync()

{

string url = "http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx";

WebClient client = new WebClient();

Task<string> t = client.DownloadStringTaskAsync(new Uri(url));

t.Wait();// 작업이 완료되때까지 대기

Debug.WriteLine(t.Result);

}

Page 26: C#을 이용한 task 병렬화와 비동기 패턴

private void Button_Click(object sender, RoutedEventArgs e)

{

string url = "http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx";

WebClient client = new WebClient();

Task<string> t = client.DownloadStringTaskAsync(new Uri(url));

t.ContinueWith((prevTask) => Debug.WriteLine(prevTask.Result));

}

Page 27: C#을 이용한 task 병렬화와 비동기 패턴

async Task<int> FuncAsync() {int r = await DoAsync();return r;

}

• TAP과함께

• 비동기함수의이름은

XxxAsync()/XxxTaskAsync()

• async와 await는함께

• 반환형은 Task, Task<TResult>

Page 28: C#을 이용한 task 병렬화와 비동기 패턴

Click

async Task LoadSettingsAsync() {

await IO.Network.DownloadAsync(path);

}

async void Button1_Click(){

await LoadSettingsAsync();

UpdateView();

}

Click

Mess

ag

ep

um

p

Task ...DownloadAsync

Task ...LoadSettingsAsync

Download

LoadSettings

Page 29: C#을 이용한 task 병렬화와 비동기 패턴

private async void Button_Click(object sender, RoutedEventArgs e)

{

string url = "http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx";

WebClient client = new WebClient();

string t = await client.DownloadStringTaskAsync(new Uri(url));

Debug.WriteLine(t);

}

Page 30: C#을 이용한 task 병렬화와 비동기 패턴