C#을 이용한 task 병렬화와 비동기 패턴
-
Upload
- -
Category
Engineering
-
view
963 -
download
19
Transcript of C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 Task 병렬화와 비동기 패턴-한국마이크로소프트 에반젤리스트 김명신 부장
12월의 주제
C#완벽분석, 원샷 올킬!
•
•
•
•
• DLL Thread attach/detach notification
• Context Switching
대략 1053KB 남짓DLL이많으면많을수록,
스레드가많으면많을수록
우리가 TASK 병렬화를알아야하는이유
Thread pool
Requests Queue
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();
// 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 결과 획득
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");
}}
// 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 결과 획득
// 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);
// 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();
intint int
int []
60초
30초
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
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);
}
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));
}
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);
}
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);
}
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));
}
async Task<int> FuncAsync() {int r = await DoAsync();return r;
}
• TAP과함께
• 비동기함수의이름은
XxxAsync()/XxxTaskAsync()
• async와 await는함께
• 반환형은 Task, Task<TResult>
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
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);
}