델리게이트 이벤트 스레드 애트리뷰트 예외 [2/53]
C# 언어의고급프로그래밍기법 응용프로그램을보다짜임새있고원롞적으로작성가능델리게이트 객체지향특성이반영된메소드포인터이벤트와스레드를처리하는방법롞 애트리뷰트 프로그래밍단위 ( 어셈블리, 클래스, 메소드등 ) 에줄수있는추가적인정보언어시스템에서실행시갂에다양하게홗용할수있는방법을지원 예외처리 실행중에발생하는에러언어시스템에서에러처리를지원 [3/53]
델리게이트 (delegate) 는메소드참조기법객체지향적특징이반영된메소드포인터 이벤트와스레드를처리하기위한방법롞 특징정적메소드및인스턴스메소드참조가능 객체지향적델리게이트의형태와참조하고자하는메소드의형태는항상일치 타입안정적델리게이트객체를통하여메소드를호출 메소드참조 VS. 함수포인터 (C/C++) 메소드참조기법면에서유사객체지향적이며타입안정적 [4/53]
정의형태 [modifiers] delegate returntype DelegateName(parameterList); 수정자 접근수정자 new public, protected, internal, private 클래스밖에서는 public 과 internal 맊가능 델리게이트정의시주의점 델리게이트할메소드의메소드반홖형및매개변수의개수, 반홖형을일치시켜야함 [5/53]
델리게이트정의예 delegate void SampleDelegate(int param); // 델리게이트정의 class DelegateClass { public void DelegateMethod(int param) { // 델리게이트할메소드 //... [6/53]
델리게이트를사용하기위해서는델리게이트객체를생성하고대상메소드를연결해야함 해당델리게이트의매개변수로메소드의이름을명시 델리게이트객체에연결할수있는메소드는형태가동일하면인스턴스메소드뿐맊아니라정적메소드도가능 델리게이트생성 ( 인스턴스메소드 ) 델리게이트할메소드가포함된클래스의객체를먼저생성 정의된델리게이트형식으로델리게이트객체를생성 생성된델리게이트를통하여연결된메소드의호출 델리게이트객체생성예 DelegateClass obj = new DelegateClass(); SampleDelegate sd = new SampleDelegate(obj.DelegateMethod); [7/53]
델리게이트객체의호출은일반메소드의호출과동일 델리게이트를통하여호출할메소드가매개변수를갖는다면델리게이트를호출하면서 ( ) 안에매개변수를기술 [8/53]
[ 예제 6.1 - DelegateCallApp.cs] using System; delegate void DelegateOne(); // delegate with no params delegate void DelegateTwo(int i); // delegate with 1 param class DelegateClass { public void MethodA() { Console.WriteLine("In the DelegateClass.MethodA..."); public void MethodB(int i){ Console.WriteLine("DelegateClass.MethodB, i = " + i); class DelegateCallApp { public static void Main() { DelegateClass obj = new DelegateClass(); DelegateOne d1 = new DelegateOne(obj.MethodA); DelegateTwo d2 = new DelegateTwo(obj.MethodB); d1(); // invoke MethodA() in DelegateClass d2(10); // invoke MethodB(10) in DelegateClass 실행결과 : In the DelegateClass.MethodA... DelegateClass.MethodB, i = 10 [9/53]
하나의델리게이트객체에형태가동일한여러개의메소드를연결하여사용가능 C# 언어는델리게이트를위한 + 와 연산자 ( 메소드추가 / 제거 ) 를제공 멀티캐스트델리게이션 (multicast delegation) 델리게이트연산을통해하나의델리게이트객체에여러개의메소드가연결되어있는경우, 델리게이트호출을통해연결된모든메소드를한번에호출 델리게이트를통하여호출되는순서는등록된순서와동일 [10/53]
[ 예제 6.2 - MultiCastApp.cs] using System; delegate void MultiCastDelegate(); class Schedule { public void Now() { Console.WriteLine("Time : "+DateTime.Now.ToString()); public static void Today() { Console.WriteLine("Date : "+DateTime.Today.ToString()); class MultiCastApp { public static void Main() { Schedule obj = new Schedule(); MultiCastDelegate mcd = new MultiCastDelegate(obj.Now); mcd += new MultiCastDelegate(Schedule.Today); mcd(); 실행결과 : Time : 2005-06-11 오후 12:05:30 Date : 2005-06-11 오젂 12:00:00 [11/53]
이벤트 (event) 사용자행동에의해발생하는사건어떤사건이발생한것을알리기위해보내는메시지 C# 에서는이벤트개념을프로그래밍언어수준에서지원 이벤트처리기 (event handler) 발생한이벤트를처리하기위한메소드 이벤트 - 주도프로그래밍 (event-driven programming) 이벤트와이벤트처리기를통하여객체에발생한사건을다른객체에통지하고그에대한행위를처리하도록시키는구조를가짐 각이벤트에따른작업을독립적으로기술 프로그램의구조가체계적 / 구조적이며복잡도를줄일수있음 [12/53]
정의형태 [event-modifier] event DelegateType EventName; 수정자 접근수정자 new, static, virtual, sealed, override, abstract, extern 이벤트처리기는메소드로배정되기때문에메소드수정자와종류 / 의미가같음 [13/53]
이벤트정의순서 1 이벤트처리기를작성 2 이벤트처리기의형태와일치하는델리게이트를정의 ( 또는 System.EventHandler 델리게이트를사용 ) 3 델리게이트를이용하여이벤트를선언 ( 미리정의된이벤트인경우에는생략 ) 4 이벤트에이벤트처리기를등록 5 이벤트를발생 ( 미리정의된이벤트는사용자행동에의해이벤트가발생 ) 이벤트가발생되면등록된메소드가호출되어이벤트를처리 미리정의된이벤트발생은사용자의행동에의해서발생 사용자정의이벤트인경우에는명시적으로델리게이트객체를호출함으로써이벤트처리기를작동 [14/53]
[ 예제 6.4 - EventHandlingApp.cs] using System; public delegate void MyEventHandler() // 2 이벤트를위한델리게이트정의 class Button { public event MyEventHandler Push; // 3 이벤트선언 public void OnPush() { if (Push!= null) Push(); // 5 이벤트발생 class EventHandlerClass { public void MyMethod() { // 1 이벤트처리기작성 Console.WriteLine("In the EventHandlerClass.MyMethod..."); class EventHandlingApp { public static void Main() { Button button = new Button(); EventHandlerClass obj = new EventHandlerClass(); button.push += new MyEventHandler(obj.MyMethod); // 4 등록 button.onpush(); 실행결과 : In the EventHandlerClass.MyMethod... [15/53]
이벤트처리기등록 델리게이트객체에메소드를추가 / 삭제하는방법과동일 사용연산자 = : 이벤트처리기등록 + : 이벤트처리기추가 - : 이벤트처리기제거 Event = new DelegateType(Method); // 이벤트처리기등록 Event += new DelegateType(Method); // 이벤트처리기추가 Event -= new DelegateType(Method); // 이벤트처리기제거 [16/53]
C# 언어에서의이벤트사용 프로그래머가임의의형식으로델리게이트를정의하고이벤트를선언할수있도록허용.NET 프레임워크는이미정의된 System.EventHandler 델리게이트를이벤트에사용하는것을권고 System.EventHandler delegate void EventHandler(object sender, EventArgs e); 이벤트와윈도우홖경 이벤트는사용자와상호작용을위해주로사용 윈도우프로그래밍홖경에서사용하는폼과수맋은컴포넌트와컨트롟에는다양한종류의이벤트가존재 프로그래머로하여금적젃히사용할수있도록방법롞을제공한 [17/53]
[ 예제 6.5 - ClickEventApp.cs] using System; using System.Windows.Forms; class ClickEventApp : Form { public ClickEventApp() { 실행결과 : // 생성자 this.text = "ClickEventApp"; this.click += new EventHandler(ClickEvent); // 등록 //... 이벤트처리기... private void ClickEvent(object sender, EventArgs e) { MessageBox.Show(" sender = " + sender.gettype()); public static void Main() { Application.Run(new ClickEventApp()); [18/53]
순차프로그램 (sequential program) 각프로그램별로시작, 순차적실행그리고종료를가짐 프로그램의실행과정중오직하나의실행점 (execution point) 을갖고있음 스레드 순차프로그램과유사하게시작, 실행, 종료의순서를가짐 실행되는동안에한시점에서단일실행점을가짐 프로그램내에서맊실행가능 스레드는프로그램내부에있는제어의단일순차흐름 (single sequential flow of control) 단일스레드개념은순차프로그램과유사 [19/53]
멀티스레드 (multithread) 시스템 스레드가하나의프로그램내에여러개존재 공유힙 (shared heap) 과공유데이터 (shared data), 그리고코드를공유함으로써문맥젂홖 (context switching) 시적은부담을가짐 한개의프로그램내에서동일시점에각각다른작업을수행하는여러개의스레드가존재하므로복잡한문제들이야기될수있음 C# 에서는언어수준에서스레드를지원 [20/53]
단일스테드시스템과멀티스레드시스템의구조비교 [21/53]
C# 에서의스레드개념 객체이며스레드가실행하는단위는메소드스레드객체를위해 Thread 클래스를제공메소드연결을위해 ThreadStart 델리게이트를제공 (System.Threading) 스레드프로그래밍의순서 1 스레드몸체에해당하는메소드를작성 2 작성된메소드를 ThreadStart 델리게이트에연결 3 생성된델리게이트를이용하여스레드객체를생성 4 스레드의실행을시작 (Start() 메소드를호출 ) [22/53]
[ 예제 6.6 SimpleThreadApp.cs] using System; using System.Threading; // 반드시포함!!! class SimpleThreadApp { static void ThreadBody() { for (int i = 0; i < 5; i++) { Console.WriteLine(DateTime.Now.Second + " : " + i); Thread.Sleep(1000); public static void Main() { ThreadStart ts = new ThreadStart(ThreadBody); Thread t = new Thread(ts); Console.WriteLine("*** Start of Main"); t.start(); Console.WriteLine("*** End of Main"); 실행결과 : *** Start of Main *** End of Main 15 : 0 16 : 1 17 : 2 18 : 3 19 : 4 // --- 1 // --- 2 // --- 3 // --- 4 [23/53]
스레드프로퍼티 프로퍼티 설명 Thread.CurrentThread 현재실행중인스레드객체를반홖한다. Thread.IsAlive 스레드의실행여부를반홖한다. Thread.Name 스레드의이름을지정하거나반홖한다. Thread.IsBackground 스레드가백그라운드스레드인지의여부를반홖한다. Thread.ThreadState 스레드의상태를반홖한다. Thread.Priority 해당스레드의우선순위를지정하거나반홖한다. [24/53]
스레드의상태도 상태 : Unstarted, Running, Suspended, Stopped 시작메소드 : Start() 종료조건 : 메소드의종료, Abort() 실행 종료 [25/53]
스레드의상태변경메소드 메소드 기능 Thread.Start() 해당스레드를실행한다. Thread.Abort() 해당스레드를종료시킨다. Thread.Join() 해당스레드의실행이종료될때까지기다린다. Thread.Suspend() 해당스레드를대기상태로맊든다. Thread.Resume() 대기상태스레드를실행상태로맊든다. Thread.Sleep() 지정한시갂동안실행을멈추고대기상태로갂다. [26/53]
[ 예제 6.8 ThreadStateApp.cs] using System; using System.Threading; class ThreadState { public void ThreadBody() { while (true) { //... infinite loop... class ThreadStateApp { public static void Main() { ThreadState obj = new ThreadState(); ThreadStart ts = new ThreadStart(obj.ThreadBody); Thread t = new Thread(ts); Console.WriteLine("Step 1: " + t.threadstate); t.start(); Thread.Sleep(100); Console.WriteLine("Step 2: " + t.threadstate); t.suspend(); Thread.Sleep(100); Console.WriteLine("Step 3: " + t.threadstate); t.resume(); Thread.Sleep(100); Console.WriteLine("Step 4: + t.threadstate); t.abort(); Thread.Sleep(100); Console.WriteLine("Step 5: " + t.threadstate); 실행결과 : Step 1: Unstarted Step 2: Running Step 3: Suspended Step 4: Runnable Step 5: Stopped [27/53]
정의 특징 실행가능한상태에있는여러스레드의실행순서를제어하는것 스레드의스케줄링에따라스레드의작업순서가달라지며, 스레드의우선순위 (priority) 에따라실행순서가결정 스레드가생성될때그스레드를맊든스레드의우선순위가상속되며 Thread.Priority 프로퍼티를통해서참조하거나변경가능 ThreadPriority 열거형원소 멤버 설명 Highest 가장높은우선순위를나타낸다. AboveNormal 높은우선순위를나타낸다. Normal 표준우선순위를나타낸다. BelowNormal 낮은우선순위를나타낸다. Lowest 가장낮은우선순위를나타낸다 [28/53]
[ 예제 6.10 ThreadPriorityApp.cs] using System; using System.Threading; class ThreadPriorityApp { static void ThreadBody() { Thread.Sleep(1000); public static void Main() { Thread t = new Thread(new ThreadStart(ThreadBody)); t.start(); Console.WriteLine("Current Priority : " + t.priority); ++t.priority; Console.WriteLine("Higher Priority : " + t.priority); 실행결과 : Current Priority : Normal Higher Priority : AboveNormal [29/53]
비동기스레드 각각의스레드는그의실행에필요한모든자료와메소드를포함 병행으로실행중인다른스레드의상태또는행위에관계되지않는자싞맊의공갂에서실행 동기스레드 동시에실행되는스레드들이자료를공유 다른스레드의상태와행위를고려 동기화문제 [30/53]
lock 문 동일한객체에대하여여러스레드의중첩실행을방지 lock 문은아토믹루틴 (atomic routine) 이되어실행순서를제어 lock 문의형태 lock (object obj) < 문장 > [31/53]
[ 예제 6.12 LockStApp.cs] public void ThreadBody() { Thread myself = Thread.CurrentThread; lock (this) { for (int i = 1; i <= 3; i++) { Console.WriteLine("{0 is activated => {1", myself.name, i); Thread.Sleep(1000); 실행결과 : Apple is activated => 1 Apple is activated => 2 Apple is activated => 3 Orange is activated => 1 Orange is activated => 2 Orange is activated => 3 [32/53]
Monitor 클래스 임의의객체에대한특정작업을동기화를하기위해사용 Monitor.Enter() 와 Monitor.Exit() 사이에실행되는작업을동기적으로실행 Monitor 클래스의메소드 메소드 Enter(Object obj) Exit(Object obj) 설명 매개변수로젂달된스레드객체가특정문장을선점할수있도록지정한다. Enter() 메소드를통하여특정문장의실행을선점한스레드를다른스레드가접근할수있도록해지한다. [33/53]
[ 예제 6.13 MonitorApp.cs] public void ThreadBody() { Thread myself = Thread.CurrentThread; Monitor.Enter(this); for (int i = 1; i <= 3; i++) { Console.WriteLine("{0 is activated => {1", myself.name, i); Thread.Sleep(1000); Monitor.Exit(this); 실행결과 : Apple is activated => 1 Apple is activated => 2 Apple is activated => 3 Orange is activated => 1 Orange is activated => 2 Orange is activated => 3 [34/53]
애트리뷰트의특징어셈블리나클래스, 필드, 메소드, 프로퍼티등에다양한종류의속성정보를추가하기위해서사용어셈블리에메타데이터 (metadata) 형식으로저장되며, 이를참조하는.NET 프레임워크나 C# 또는다른언어의컴파일러에의해다양한용도로사용 애트리뷰트의정의형태 [attribute AttributeName ("positional_parameter", named_parameter = value,...)] 애트리뷰트의종류표준애트리뷰트 (.NET 프레임워크에서제공 ) 사용자정의애트리뷰트 [35/53]
Conditional 애트리뷰트 조건부메소드를작성할때사용 C/C++ 언어에서사용했던젂처리기지시어를이용하여명칭을정의 (#define) System.Diagnostics 를사용해야함 Obsolete 애트리뷰트 앞으로사용되지않을메소드를표시하기위해서사용 해당애트리뷰트를가짂메소드를호출할경우컴파일러는컴파일과정에서애트리뷰트에설정한내용이출력하는경고를발생 [36/53]
[ 예제 6.15 ObsoleteApp.cs] using System; class ObsoleteAttrApp { [Obsolete(" 경고, Obsolete Method 입니다.")] public static void OldMethod() { Console.WriteLine("In the Old Method..."); public static void NormalMethod() { Console.WriteLine("In the Normal Method..."); public static void Main() { ObsoleteAttrApp.OldMethod(); ObsoleteAttrApp.NormalMethod(); 실행방법 : C:\> csc ObsoleteAttrApp.cs ObsoleteAttrApp.cs(11,13): warning CS0618: ObsoleteAttrApp.OldMethod() 은 ( 는 ) 사용되지않습니다. ' 경고, Obsolete Method 입니다.' 실행결과 : In the Old Method... In the Normal Method... [37/53]
특징 System.Attribute 클래스에서파생이름의형태 : XxxxAttribute 정의한애트리뷰트를사용할때는이름에서 Attribute 가제외된부분맊을사용 사용자정의애트리뷰트나표준애트리뷰트를사용하기위해서는.NET 프레임워크가제공하는리플렉션기능을사용 // 사용자정의애트리뷰트를정의한예 public class AttributeNameAttribute: Attribute { // 생성자정의 //... // 사용자정의애트리뷰트를사용한예 [AttributeName()] [38/53]
[ 예제 6.16 MyAttributesApp.cs] using System; public class MyAttrAttribute: Attribute { // 속성클래스 public MyAttrAttribute(string message) { // 생성자 this.message = message; private string message; public string Message { // 프로퍼티 get { return message; [MyAttr("This is Attribute test.")] class MyAttributeApp { public static void Main() { Type type = typeof(myattributeapp); object[] arr = type.getcustomattributes(typeof(myattrattribute), true); if (arr.length == 0) Console.WriteLine("This class has no custom attrs."); else { MyAttrAttribute ma = (MyAttrAttribute) arr[0]; Console.WriteLine(ma.Message); 실행결과 : This is Attribute test. [39/53]
예외 (exception) 실행시갂에발생하는에러 (run-time error) 프로그램의비정상적인종료잘못된실행결과메소드의호출과실행, 부정확한데이터, 그리고시스템에러등다양한상황에의해야기 예외처리 (exception handling) 기대되지않은상황에대해예외를발생야기된예외를적젃히처리 (exception handler) 예외처리를위한방법을언어시스템에서제공응용프로그램의싞뢰성 (reliability) 향상예외검사와처리를위한프로그램코드를소스에깔끔하게삽입 [40/53]
예외도하나의객체로취급따라서, 먼저예외를위한클래스를정의하여야함 예외클래스모든예외는형 (type) 이 Exception 클래스또는그의파생클래스들중에하나로부터확장된클래스의객체일반적으로프로그래머는 Exception 클래스의파생클래스인 ApplicationException 클래스를확장하여새로운예외클래스를정의하여사용 예외를명시적으로발생시키면예외를처리하는예외처리기가반드시필요함 예외에관렦된메시지를스트링형태로예외객체에담아젂달가능 [41/53]
[ 예제 6.17 UserExceptionApp.cs] using System; class UserErrException : ApplicationException { public UserErrException(string s) : base(s) { class UserException { public static void Main() { try { throw new UserErrException("throw a exception with a message"); catch (UserErrException e) { Console.WriteLine(e.Message); 실행결과 : throw a exception with a message [42/53]
시스템정의예외 (system-defined exception) 프로그램의부당한실행으로인하여시스템에의해묵시적으로일어나는예외 SystemException 클래스나 IOException 클래스로부터확장된예외 CLR 에의해자동적으로생성 야기된예외에대한예외처리기의유무를컴파일러가검사하지않음 (unchecked exception) 프로그래머정의예외 (programmer-defined exception) 프로그래머에의해의도적으로야기되는프로그래머정의예외 프로그래머정의예외는발생한예외에대한예외처리기가존재하는지컴파일러에의해검사 (checked exception) [43/53]
예외클래스의계층도 [44/53]
시스템정의예외의종류 ArithmeticException 산술연산시발생하는예외 IndexOutOfRangeException 배열, 스트링, 벡터등과같이인덱스를사용하는객체에서인덱스의범위가벖어날때발생하는예외 ArrayTypeMismatchException 배열의원소에잘못된형의객체를배정하였을때발생하는예외 InvalidCastException 명시적형변홖이실패할때발생하는예외 NullReferenceException null 을사용하여객체를참조할때발생하는예외 OutOfMemoryException 메모리할당 (new) 이실패하였을때발생하는예외 [45/53]
묵시적예외발생 시스템정의예외로 CLR 에의해발생 시스템에의해발생되므로프로그램어디서나발생가능 프로그래머가처리하지않으면디폴트예외처리기 (default exception handler) 에의해처리 명시적예외발생 throw 문을이용하여프로그래머가의도적으로발생 throw ApplicationExceptionObject; 프로그래머정의예외는생성된메소드내부에예외를처리하는코드부분인예외처리기를두어직접처리해야함 [46/53]
[ 예제 6.19 UserExThrowApp.cs] using System; class UserException : ApplicationException { class UserExThrowApp { static void Method() { throw new UserException(); public static void Main() { try { Console.WriteLine("Here: 1"); Method(); Console.WriteLine("Here: 2"); catch (UserException) { Console.WriteLine("User-defined Exception"); 실행결과 : Here: 1 User-defined Exception [47/53]
에러처리구문 (try-catch-finally 구문 ) 예외를검사하고처리해주는문장 구문형태 try { //... "try 블록 catch (ExceptionType identifier) { //... "catch 블록 catch (ExceptionType identifier) { //... "catch 블록 finally { //... "finally 블록 try 블록 : 예외검사 catch 블록 : 예외처리 finally 블록 : 종결작업, 예외발생과무관하게반드시실행 [48/53]
에러처리기의실행순서 1 try 블록내에서예외가검사되고또는명시적으로예외가발생하면, 2 해당하는 catch 블록을찾아처리하고, 3 마지막으로 finally 블록을실행한다. Default 예외처리기 시스템정의예외가발생됐는데도불구하고프로그래머가처리하지않을때작동 단순히에러에대한메시지를출력하고프로그램을종료하는기능 [49/53]
[ 예제 6.24 FinallyClauseApp.cs] using System; class FinallyClauseApp { static int count = 0; public static void Main() { while (true) { try { if (++count == 1) throw new Exception(); if (count == 3) break; Console.WriteLine(count + ") No exception"); catch (Exception) { Console.WriteLine(count + ") Exception thrown"); finally { Console.WriteLine(count + ") in finally clause"); // end while Console.WriteLine("Main program ends"); 실행결과 : 1) Exception thrown 1) in finally clause 2) No exception 2) in finally clause 3) in finally clause Main program ends [50/53]
호출한메소드로예외를젂파 (propagation) 하여특정메소드에서모아처리 예외처리코드의분산을막을수있음 예외젂파순서 예외를처리하는 catch 블록이없으면호출한메소드로예외를젂파함 예외처리기를찾을때까지의모든실행은무시 [51/53]
예외젂파과정 System.DivideByZeroException: at PropagateApp.Orange() in c:\csharp\chapter6\propagateapp.cs: line 5 at PropagateApp.Apple() in c:\csharp\chapter6\propagateapp.cs: line 8 at PropagateApp.Main() in c:\charp\chapter6\propagateapp.cs: line 12 [52/53]
[ 예제 6.25 PropagateApp.cs] using System; class PropagateApp { void Orange() { int i = 25, j = 0; i = i / j; Console.WriteLine("End of Orange method"); void Apple() { Orange(); Console.WriteLine("End of Apple method"); public static void Main() { PropagateApp p = new PropagateApp(); try { p.apple(); catch (ArithmeticException) { Console.WriteLine("ArithmeticException is processed"); Console.WriteLine("End of Main"); 실행결과 : ArithmeticException is processed End of Main [53/53]