<4D F736F F D20BEBEBCA520C4DAB5F920BFACBDC0202D20B8D6C6BC20BEB2B7B9B5E5BFCD20C0CCBAA5C6AE2E646F6378>

Similar documents
(Microsoft Word - C# \304\332\265\371 \277\254\275\300.docx)

gnu-lee-oop-kor-lec06-3-chap7

PowerPoint Presentation

작성자 : 김성박\(삼성 SDS 멀티캠퍼스 전임강사\)

JAVA PROGRAMMING 실습 08.다형성

Microsoft PowerPoint - CSharp-10-예외처리

JAVA PROGRAMMING 실습 05. 객체의 활용

Microsoft PowerPoint - hci2-lecture12 [호환 모드]

Design Issues

<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - Java7.pptx

PowerPoint Presentation

어댑터뷰

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

(Microsoft PowerPoint - hci2-lecture12 [\310\243\310\257 \270\360\265\345])

PowerPoint Presentation

1. auto_ptr 다음프로그램의문제점은무엇인가? void func(void) int *p = new int; cout << " 양수입력 : "; cin >> *p; if (*p <= 0) cout << " 양수를입력해야합니다 " << endl; return; 동적할

JVM 메모리구조

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

PowerPoint Presentation

JAVA PROGRAMMING 실습 09. 예외처리

PowerPoint Presentation

JAVA PROGRAMMING 실습 02. 표준 입출력

Microsoft PowerPoint - chap06-2pointer.ppt

Microsoft PowerPoint - Chap12-OOP.ppt

Microsoft PowerPoint 장강의노트.ppt

WS12. Security

Microsoft PowerPoint - ch07 - 포인터 pm0415

슬라이드 1

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

API - Notification 메크로를통하여어느특정상황이되었을때 SolidWorks 및보낸경로를통하여알림메시지를보낼수있습니다. 이번기술자료에서는메크로에서이벤트처리기를통하여진행할예정이며, 메크로에서작업을수행하는데유용할것입니다. 알림이벤트핸들러는응용프로그램구현하는데있어

쉽게 풀어쓴 C 프로그래밍

Microsoft Word - Crackme 15 from Simples 문제 풀이_by JohnGang.docx

5장.key

C# Programming Guide - Types

쉽게 풀어쓴 C 프로그래밍

11장 포인터

PowerPoint Presentation

Microsoft PowerPoint - Lect04.pptx

(8) getpi() 함수는정적함수이므로 main() 에서호출할수있다. (9) class Circle private double radius; static final double PI= ; // PI 이름으로 로초기화된정적상수 public

PowerPoint Presentation

Microsoft PowerPoint - 04-UDP Programming.ppt

예제 2) Test.java class A intvar= 10; void method() class B extends A intvar= 20; 1"); void method() 2"); void method1() public class Test 3"); args) A

Cluster management software

쉽게 풀어쓴 C 프로그래밍

비긴쿡-자바 00앞부속

쉽게 풀어쓴 C 프로그래밍

PowerPoint Template

Microsoft PowerPoint - 2강

PowerPoint 프레젠테이션

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

JAVA PROGRAMMING 실습 02. 표준 입출력

Microsoft PowerPoint 자바-기본문법(Ch2).pptx

슬라이드 1

PowerPoint 프레젠테이션

1. 객체의생성과대입 int 형변수 : 선언과동시에초기화하는방법 (C++) int a = 3; int a(3); // 기본타입역시클래스와같이처리가능 객체의생성 ( 복습 ) class CPoint private : int x, y; public : CPoint(int a

PowerPoint 프레젠테이션

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

Microsoft PowerPoint - java1-lab5-ImageProcessorTestOOP.pptx

JAVA PROGRAMMING 실습 05. 객체의 활용

PowerPoint Presentation

Spring Data JPA Many To Many 양방향 관계 예제

untitled

snu.pdf

199

b

rmi_박준용_final.PDF

Microsoft PowerPoint - Chapter 6.ppt

02 C h a p t e r Java

C++ Programming

Microsoft PowerPoint - CSharp-2-기초문법

제11장 프로세스와 쓰레드

슬라이드 1

쉽게 풀어쓴 C 프로그래밍

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

PowerPoint Presentation

설계란 무엇인가?

목차 BUG DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4

<4D F736F F F696E74202D20C1A63034B0AD202D20C7C1B7B9C0D3B8AEBDBAB3CABFCD20B9ABB9F6C6DBC0D4B7C2>

(Microsoft PowerPoint - java1-lecture11.ppt [\310\243\310\257 \270\360\265\345])

유니티 변수-함수.key

mytalk

API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Docum

Microsoft PowerPoint - TimeTable System.pptx

1. 상속의기본개념 다음과같은문제를위한클래스설계 자동차 속성 : 색상, 배기량, 현재속도 메서드 : 가속하라, 멈춰라, 시동을켜라 트럭 속성 : 색상, 배기량, 현재속도, 최대중량 메서드 : 가속하라, 멈춰라, 시동을켜라 택시 속성 : 색상, 배기량, 현재속도, 요금,

2014밝고고운동요부르기-수정3

2005프로그램표지

제8장 자바 GUI 프로그래밍 II

PowerPoint 프레젠테이션

Microsoft PowerPoint - additional08.ppt [호환 모드]

Microsoft PowerPoint - 14주차 강의자료

PowerPoint 프레젠테이션

@OneToOne(cascade = = "addr_id") private Addr addr; public Emp(String ename, Addr addr) { this.ename = ename; this.a

파일로입출력하기II - 파일출력클래스중에는데이터를일정한형태로출력하는기능을가지고있다. - PrintWriter와 PrintStream을사용해서원하는형태로출력할수있다. - PrintStream은구버전으로가능하면 PrintWriter 클래스를사용한다. PrintWriter

TEST BANK & SOLUTION

자바 프로그래밍

A Dynamic Grid Services Deployment Mechanism for On-Demand Resource Provisioning

Network Programming

gnu-lee-oop-kor-lec10-1-chap10

C++ Programming

Transcription:

C# 코딩연습 멀티쓰레드와이벤트 2009-05-18 김태현 (kimgwajang@hotmail.com)

I. 서 제블로그 1 의카테고리중에.NET Tip of The Day' 라는것이있는데, 동명의사이트 2 에실린유용한닷넷팁들을번역하여소개하는포스팅이모여있습니다. 이중 Correct event invocation 3 라는제목의포스트가있는데, 멀티쓰레드환경에서이벤트를호출하는올바른방법에관해서설명을하고있습니다. 원문의설명자체는간단합니다. 이벤트를호출하는통상적인코드는보통아래와같은데, 1 public event EventHandler SelectedNodeChanged; 2 3 protected virtual void OnSelectedNodeChanged(object sender, EventArgs e) 4 { 5 if (SelectedNodeChanged!= null) 6 SelectedNodeChanged(this, e); 7 } 코드 1 멀티쓰레드환경에서는이코드가문제를일으킬수있기때문에, 아래와같이변경하는것이 ( 멀티쓰레드환경에서의 ) 올바른이벤트호출 이라는것입니다. 1 public event EventHandler SelectedNodeChanged; 2 3 protected virtual void OnSelectedNodeChanged(object sender, EventArgs e) 4 { 5 EventHandler handler = SelectedNodeChanged; 6 7 if (handler!= null) 8 handler(this, e); 9 } 코드 2 이코드를이해하기위해서는몇가지배경지식이필요한데, 이번 C# 코딩연습에서는이를 다루어보고자합니다. 1 http://kimgwajang.tistory.com 2 http://dotnettipoftheday.org 3 http://dotnettipoftheday.org/tips/correct-event-invocation.aspx 1

II. 불변 (immutable) 객체 불변객체란한번생성되면그상태가변하지않는객체를말합니다. 4 닷넷프레임웍에도몇 가지불변객체들이있는데, 대표적으로 System.String 형을들수있습니다. 여기서돌발퀴즈! 1 string a = " 원본 "; 2 string b = a; 3 4 a = " 수정 "; 5 6 Console.WriteLine(b); 코드 3 화면에 원본 이찍힐까요, 수정 이찍힐까요? 결과는아래와같습니다. 원본계속하려면아무키나누르십시오... 조금이상하지않습니까? 아시다시피 string 은참조형 5 입니다. 그래서 1 번에서 a 는메모리의 어딘가에생성된 원본 이라는데이터에대한참조입니다. 그림 1 2 번라인에서 b 역시참조인데, 이의값은 a 가가리키는값, 즉 원본 입니다. 4 http://en.wikipedia.org/wiki/immutable_object 5 값형과참조형을구분하고각각의성격을정확하게파악하는것은닷넷에서너무너무중요한일입니다. 박싱과언박싱이제네릭과어떻게연결되는지를이해하는수준이되면기초가탄탄하다고할수있을것같습니다. 2

그림 2 이상태에서 4 번라인에서 a 가가리키는값을 수정 이라고변경했습니다. 그림 3 이상태에서 b 의값을출력하면당연히 수정 이나와야할텐데, 결과는 원본 이찍혔습니다. 무엇이잘못된것일까요? String 형이일반적인참조형이라면이설명이맞습니다만, 닷넷프레임웍의설계자들은 String 을특수한참조형인불변객체로구현하였습니다. 불변객체는생성되고나면값이변하지않습니다. 하지만그림 2 와같이 b 가 a 와같은객체를가리킨다면그림 3 과같이 b 를이용해 a 의값을변경할수있게됩니다. 이를막기위해불변객체는 2 번라인과같이참조가복사 ( 얕은복사 ) 될때내부적으로객체자체를복사 ( 깊은복사 ) 하여버립니다. 즉 2 번라인이실행되고나면그림 2 가아니라아래와같은상태가됩니다. 3

그림 4 b 가 a 와같은참조를가지는것이아니라 a 가참조하는객체 (100 번지 ) 를복사하여새로만든 후 (200 번지 ) b 는이객체를참조하게됩니다. 따라서처음생성된 100 번지에있는객체에 접근할수있는참조는여전히 a 밖에없게됩니다. 이상태에서 4 번라인이실행되어 a 가참조하는객체를 수정 으로변경하면그림 3 이아니라 아래와같은모습이됩니다. 그림 5 메모리를조금더소비하지만성능을높일수있다는이유와멀티쓰레드환경에서쓰레드에 안전한객체를만들수있다는등의이유로닷넷프레임웍에는다수의불변객체가구현되어 있습니다. 오늘의주제인대리자역시불변객체입니다. 코드를볼까요? 01 private static void Main(string[] args) 02 { 03 Action action1 = new Action(Print1); 04 Action action2 = action1; 05 06 action1 = null; 07 08 action2(); 4

09 } 10 11 public static void Print1() 12 { 13 Console.WriteLine("1"); 14 } 코드 4 1 이출력될까요? 아니면널참조예외가발생할까요? 1 계속하려면아무키나누르십시오... Action 은 Func 과더불어닷넷프레임웍 2.0 에서추가된대리자입니다. 사용 자정의대리자형식을만들기보다는 Action 혹은 Func 대리자를사용하실 것을추천합니다. 참고로 Action 은제네릭과제네릭이아닌두가지형식이 각각존재합니다. 3 번라인에서 Print1 을가리키는대리자객체를만들고그에대한참조를 action1 에지정합니다. 4 번라인에서는 action2 에 aciton1 을복사하는데, 이때 Action 은대리자이고대리자는불변형이기때문에 action1 이가리키는참조를단순히 action2 에할당 ( 복사 ) 하는것이아니고, action1 이참조하는것과동일한객체를새로만들고 action2 에는그참조를지정합니다. 그림 4 와동일한상황이되겠습니다. 6 번라인에서 action1 이참조하는값을 null 이라고하면, ( 위그림에서의주소를예로들자면 ) action1 과 action2 는각각 100 번지와 200 번지에있는서로다른객체를가리키고있는데, 100 번지에있는객체만이해제되기때문에 200 번지에있는대리자객체를실행하는것은널참조예외를일으키지않습니다. 물론불변객체는닷넷에만있는개념은아닙니다. 여러가지언어에서불변객체의개념과 구현은오랫동안발전되어왔습니다. 그만큼불변객체에대해서는깊이있는연구와학습이 필요할테지만, 여기서는단한문장만기억하고넘어가시기바랍니다. 대리자는불변객체입니다. 5

III. 멀티쓰레드에서의이벤트호출 이번에는멀티쓰레드환경에서의이벤트호출에대해서살펴봅시다. 01 internal class Program 02 { 03 private static void Main(string[] args) 04 { 05 Person person = new Person(); 06 person.agechanged += PrintAge; 07 person.increaseage(); 08 } 09 10 public static void PrintAge(object sender, EventArgs e) 11 { 12 Person person = (Person) sender; 13 Console.WriteLine(person.Age); 14 } 15 } 16 17 public class Person 18 { 19 public int Age { get; private set; } 20 21 public event EventHandler AgeChanged; 22 23 protected virtual void OnAgeChanged(object sender, EventArgs e) 24 { 25 if (AgeChanged!= null) 26 AgeChanged(this, e); 27 } 28 29 public void IncreaseAge() 30 { 31 Age++; 32 33 OnAgeChanged(this, new EventArgs()); 34 } 35 } 코드 5 Person 클래스의 AgeChanged 이벤트에 PrintAge 라는이벤트핸들러를등록시키고 IncreaseAge 메서드를호출합니다. IncreaseAge 메서드가실행되면나이를 1 살증가시키고 OnAgeChanged 라는호출하는데, OnAgeChanged 내부에서는 AgeChanged 에등록된이벤트핸들러가있는지 (AgeChanged!= null) 검사한후, 있다면이벤트핸들러를실행합니다. 6

그런데이코드는멀티쓰레드환경에서는문제를일으킬수있습니다. 바로 25 번라인에서 26 번라인으로넘어가는순간이문제가될수있는데요. 25 번라인에서 AgeChanged 가널인지를검사합니다. 널이아님을확인한후 26 번라인을실행하려는데, 다른쓰레드가 AgeChanged 에등록된이벤트핸들러를해제해버렸습니다. 그리고다시원래쓰레드로전환되어 26 번라인을실행하면이제 AgeChanged 는널이기때문에널참조예외가발생합니다. 이를코드로표현하면다음과같습니다. 01 protected virtual void OnAgeChanged(object sender, EventArgs e) 02 { 03 if (AgeChanged!= null) 04 { 05 // 다른쓰레드로전환 06 AgeChanged -= Program.PrintAge; 07 // 원래쓰레드전환 08 09 AgeChanged(this, e); 10 } 11 } 코드 6 여기서 6 번라인은다른쓰레드에의해서실행되었음을시뮬레이션하는코드입니다. 이문제를해결하기위해서는일반적인패턴은다음과같습니다. 01 protected virtual void OnAgeChanged(object sender, EventArgs e) 02 { 03 EventHandler handler = AgeChanged; 04 05 if (handler!= null) 06 { 07 // 다른쓰레드로전환 08 AgeChanged -= Program.PrintAge; 09 // 원래쓰레드전환 10 11 handler(this, e); 12 } 13 } 코드 7 7

먼저확실히짚어둘것은, AgeChanged 의형식은 EventHandler 라는것입니다. AgeChanged 가 이벤트라는것은문법적인구분이며, AgeChanged 의형은확실히대리자인 EventHandler 입니다. ( 코드 5 의 21 번라인 ) 3 번라인에서 handler 라는새로운대리자변수를만들고기존 AgeChanged 객체의값을할당합니다. 이는 Action action2 = action1; 와동일한코드입니다. 위에서살펴봤듯이, 이때 handler 에는 AgeChanged 로부터복사된새로운대리자객체의참조가담기게됩니다. 즉, AgeChanged 와 handler 는각각의객체를따로가지고있다는것입니다. 그렇다면나머지코드는이해하기쉽습니다. 8 번라인에서의시뮬레이션과같이 AgeChanged 에등록되어있던이벤트핸들러가해제되더라도 AgeChanged 가아닌 handler 에대해널검사를하고이벤트를발생시키기때문에이제널참조예외를걱정할필요가없게된것입니다. 8