// ramda
Task task = new Task( () => PrintMessage() );
task.Start();
대표사진 삭제
사진 설명을 입력하세요.
1)대리자 + 2)람다 -> 3)비동기 -> 4) .NET 네트워크
C# 스타일에 맞는 네트워크 프로그래밍을 하려면, 비동기(Thread, Task, Async, Parallel) 구조 구현을 이해해야 한다.
C# 스타일 비동기 구조 구현을 위해서는, 대리자와 이벤트를 이해해야 한다.
C# 에서 대리자와 이벤트의 사용은 사용자 생성 대리자와, func, action 대리자에 람다를사용 할 수 있어야 한다.
C#에서 thread 보다 비동기(Task, Async, Parallel) 이 더 효과적이다.
1. TPL (Task Parallel Library : 작업 병렬 라이브러리)
.NET 4.0에 도입
Task, Task<T>, Parallel 클래스 포함해 기본적으로 다중 CPU 병렬 처리를 목적으로 한다.
쓰레드풀로부터 쓰레드를 가져와 비동기 작업을 실행
2. Task 선언 후, 즉시 실행
// .NET 4.0
Task.Factory.StartNew(() => {
Console.WriteLine("Hello Task library!"); });
// .NET 4.5
public async Task DoWork()
{
await Task.Run(() => PrintMessage());
}
3. Task 선언 후, 추후 실행
// action delegate
Task task = new Task(new Action(PrintMessage));
task.Start();
// delegate
Task task = new Task(delegate { PrintMessage(); });
task.Start();
// ramda
Task task = new Task( () => PrintMessage() );
task.Start();
// ramda & annonymous method
Task task = new Task( ( ) => { PrintMessage(); } );
task.Start();
4. Task<T>, Parallel
4.1 Task<TResult>
숫자 0~100만 중, 10개의 Task 비동기로 소수 찾기 결과
4.2 Parallel
숫자 0~100만 중, 소수 찾기 결과
5. async 한정자, await 연산자
: C# 5.0 도입
: C# 1.0 BeginInoke()/ EndInvoke() 메소드 대체
- async 한정자
: 해당 메서드가 await를 가지고 있음을 컴파일러에게 알려주는 역할
: await 연산자를 없는 경우, 동기적으로 실행
- 반환 형식 제한: Task, Task<TResult>, void
: 실행 후 잊어버릴 작업: void
: 실행 후 완료까지 대기할 작업: Task, Task<TResult>
private async void RunIt() { // 긴 계산을 하는 메서드 비동기로 호출 Task<double> task = Task<double>.Factory.StartNew(() => LongCalc(10)); // Task가 끝나기를 기다림. 하지만 UI 쓰레드는 Block되지 않는다. await task; // Task가 끝난 다음 아래 UI 컨트롤의 값 갱신 // 이 문장은 UI 쓰레드에서 실행되므로 Invoke()가 필요 없다. textBox1.Text = task.Result.ToString(); } double LongCalc(double r) { // 3초간 긴 계산 Thread.Sleep(3000); return 3.14 * r * r; }
private async void RunIt()
{
// 긴 계산을 하는 메서드 비동기로 호출
Task<double> task = Task<double>.Factory.StartNew(() => LongCalc(10));
// Task가 끝나기를 기다림. 하지만 UI 쓰레드는 Block되지 않는다.
await task;
// Task가 끝난 다음 아래 UI 컨트롤의 값 갱신
// 이 문장은 UI 쓰레드에서 실행되므로 Invoke()가 필요 없다.
textBox1.Text = task.Result.ToString();
}
double LongCalc(double r)
{
// 3초간 긴 계산
Thread.Sleep(3000);
return 3.14 * r * r;
}
6. .NET이 제공하는 비동기 API
~Async ()라는 이름의 메소드들
19. Thread
C# 은 객체지향 프로그래밍 언어다.
쓰레딩과 병렬처리 또한 객체로써 다루어진다.
- thd == Thread
- Thread
: 운영체제가 CPU 자원을 할당하는 기본 단위
- Parallel processing (병렬 처리)
: 하나의 작업을 여러개로 나눠서 처리
- Synchronous vs. Asynchronous
Eng. | Kor. | HanJa | Exp. | callback timing |
Synchronous | 동기화 | 同 무리 동 期 기약할 기 化 될 화 | 동시 발생함 | 함수 종료 직후 |
Asynchronous | 비동기화 | 非 아닐 비 | 동시 발생 안함 | 임의의 타이밍 |
19.1. Thread 생성 방법
- 매개변수 없는 Thread 생성 방법
- 매개변수 있는 Thread 생성 방법
: 파라미터를 object 로 전달하기에, 여러 개의 파라미터는 객체, 구조체로 전달
: Thread.Start() 메서드 호출시 매개변수 전달
19.2. Thread 흐름 제어
- Thread.Join( )
조인된 메서드의 실행 종료시 제어가 main 으로 복귀
- Thread.Abort( )
- 프로세스 내부의 스레드는 즉시 종료되지 않는다.
: Thread 객체에 Abort ( ) 를 호출하면 CLR은 ThreadAbortException을 던진다.
: 이때 이 예외를 catch가 있으면 처리한 다음, finally 블록까지 실행한 후 스레드가 완전히 종료된다.
: Abort ( ) 메소드를 goto 문만큼 신중하게 사용 (쓰지마라)
- ThreadState
: 비트 연산을 통해 ThreadState가 어떤 상태에 있는지 쉽 게 알아낼 수 있다
- Thread.Interrupt()
: 스레드 Running 상태를 피해서 WaitSleepJoin 상태에 들어갔을 때 ThreadInterruptedException 예외를 던져 스레드를 중지
: 최소한 코드가 “절대로 중단되면 안 되는” 작업을 하고 있을 때는 중단되지 않음 보장
19.5. Thread Synchronization - Lock, Monitor
: 자원을 한 번에 하나의 스레드가 사용하도록 보장”하는 것
- Critical Section(크리티컬 섹션): 한 번에 한 스레드만 사용할 수 있는 장치
- lock( ) = Monitor.Enter( ) + Monitor.Exit( )
19.6. Monitor.Wait( )와 Monitor.Pulse( )
- lock 대신 Monitor 를 사용해야 한다면, Wait( ) 와 Pulse( ) 메소드 영향이 크다
19.5. Thread 추가
- ThreadPool 클래스
: .NET 4.0 32bit 1023개, 64bit 32768개
: 이미 존재하는 쓰레드풀에서 사용가능한 작업 쓰레드를 할당 받아 사용하는 방식
- ThreadPool.QueueUserWorkItem()
: 리턴 값이 필요 없는 경우
- Asynchronous Delegate (비동기 델리게이트)
: 리턴값이 필요한 경우
: BeginInvoke(), IAsyncResult, EndInvoke()
- BackgroundWorker 클래스
: 이벤트 기반 비동기 처리
- Thread Affinity (쓰레드 선호도)
: UI Thread: UI 컨트롤을 생성하고 이 컨트롤의 윈도우 핸들을 소유한 쓰레드
: Worker Thread: UI 컨트롤들을 갖지 않는 쓰레드
: WinForm이나 WPF는 그 UI 컨트롤을 생성한 쓰레드만(UI 쓰레드)이 해당 UI 객체를 엑세스