posted by 방랑군 2012. 1. 21. 23:41

특정 클래스가 IEnumerable인터페이스를 구현했다면 IEnumerator를 사용해서 내부의 데이터를 순방향으로만 접근할 수 있는 기능을 가진 것이다.

IEnumerator형으로 얻은 객체는 읽기전용 커서(Cursor)를 제공하고 있으며, 데이터의 집하벵 대한 순방향으로 검색할 수 있다.


IEnumerable인터페이스에는 GetEnumerator()함수를 사용해서 IEnumerator를 얻어서 작업을 한다.

IEnumerable인터페이스는 내부에 GetEnumerator()추상함수를 포함하고 있으며, 이 함수를 이용해서 IEnumerator의 객체를 얻을 수 있다.

IEnumerator는 현재 커서 위치에서 데이터를 추출하는 기능을 지원하며 순방향으로 검색기능을 제공하는 것은 항연한 소리이다.

커서를 데이터 집합의 시작점으로 돌리는 기능도 제공한다.


Array클래스는 IEnumerable인터페이스를 구현하였기 때문에 IEnumerator를 사용할 수 있다.

다음 예제는 배열에서 IEnumerable인터페이스를 사용하는 방법을 보여주고 있다.


using System;

using System.Collections;


public class IEnumerableTest

{

public static void Main()

{

string[] authors = { "A", "B", "C", "D", "E", "F" };

IEnumerator e = authors.GetEnumerator();

while (e.MoveNext())

{

Console.WriteLine(e.Current);

}

}

}




IEnumerator객체를 얻기 위해서는 GetEnumerator()를 사용하면 된다.

모든 배열은 IEnumerator 인터페이스를 구현하고 있기 때문에 배열에 대해 GetEnumerator()함수를 호출할 수 있다.


IEnumerator객체를 얻은 후 순방향으로 순회하기 위해서 while루프에서 MoveNext()함수를 호출하면 된다.

그리고 MoveNext()로 커서를 움직인 후 커서가 위치한 곳의 데이터를 추출하기 위해서 Current 속성을 이용한다.

이 때 Current의 타입은 Object형이다.


Current포인터를 컬렉션의 처음부분앞에 있는 정의하지 않은 값으로 다시 설정할 때는 Reset()을 호출한다.

Reset()을 호출한 후 Current로 접근하기 전에 MoveNext()를 호출해야 한다.

이유는 처음에는 Current참조가 정의되지 않기 때문이다.


IEnumerator객체가 컬렉션의 마지막 위치에 있을 때 MoveNext()함수를 호출하면 false를 반환한다.

따라서 컬렉션 내의 모든 데이터에 대해 MoveNext()함수가 true를 반환하는 동안 루프를 수행하면서 false가 반환되면 빠져나오는 방법으로 데이터를 검색할 수 있다.

posted by 방랑군 2012. 1. 21. 22:46

출처 :  http://blog.naver.com/prokyhsigma?Redirect=Log&logNo=120109045619

스레드함수.cs

class ThreadTest
{
// 스레드 동기화 및 일시정지, 재시작
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private ManualResetEvent _pauseEvent = new ManualResetEvent(false);

private Thread m_thread;


public ThreadTest()
{
m_thread = new Thread(new ThreadStart(threadFunc));
m_thread.Name = "test";
m_thread.IsBackground = true;
m_thread.Start();
}


private void threadFunc()
{
int i = 0;

while(_pauseEvent.WaitOne())
{
System.Diagnostics.Trace.WriteLine(i.ToString());
i++;
Thread.Sleep(1000);

}
}


// --------------------------------------------------------------------------------
// 스레드 일시정지
// --------------------------------------------------------------------------------
public void pause()
{
_pauseEvent.Reset();
}//end pause()

// --------------------------------------------------------------------------------
// 스레드 재시작
// --------------------------------------------------------------------------------
public void resume()
{
_pauseEvent.Set();
}//end resume()

// --------------------------------------------------------------------------------
// 스레드 종료 준비, 동기화 이벤트 처리
// --------------------------------------------------------------------------------
public void readyEndThread()
{
_shutdownEvent.Set();
_pauseEvent.Set();
}//end endThread()
}
}

메인.cs

static void Main(string[] args)
{
ThreadTest test = new ThreadTest();
test.resume();

Thread.Sleep(3000);
test.pause();

Thread.Sleep(3000);
test.resume();

Thread.Sleep(30000);
}

메인 클래스에서 스레드 함수를 자유롭게 통제 가능해진다.

결과> 1, 2, 3 출력 후 3초 뒤 다시 4, 5, 6 다시 3초뒤 나머지 30초동안 뒷 숫자가 출력이 된다.

[ 주의점 ]

1. 이벤트 초기값 false로 스레드를 처음부터 일시정지 시켜놓을 수 있다. true면 바로 시작.

2. 반복문의 조건을 _pauseEvent.WaitOne()) 으로 두어서 신호를 반복문 제어값으로 해놓는다.

 
posted by 방랑군 2012. 1. 21. 22:44
멀티 스레드에서 가장 중요한 동기화 시키는 법에 대해 알아보겠습니다.

그중 MunualResetEvent 클래스를 사용해서 하는법을 알아보겠습니다.

ManualResetEvent는 서로 Signal(신호)를 통해 스레드를 작동시키는 것입니다.

그럼 필수적으로 필요한 매소드에 대해 알아보겠습니다.





ManualResetEvent의 Set() = 계속 진행되도록 신호를 받는것
ManualResetEvent의 Reset() = 스레드가 차단되어 이벤트 신호가 더이상없음을 설정하는
ManualResetEvent의 WaitOne() = 신호의 상태를 확인합니다. 
즉 Set()으로 되어있으면 true
Reset()으로 되어있으면 false 
반환합니다.
이라고 생각하시면 됩니다.

소스를 보면서 설명해 보겠습니다.기본 소스 입니다.
MyCalculator로 제가 만든 클래스 입니다.(클릭하면 크게 보입니다.)
ManualResetEvent클래스 변수 control_Thread 를 만든 후 초기화를 false로 했습니다.
WaitOne()함수는 control_Thread의 신호가 false인지,true인지 확인한 합니다.
그 후 for문을 빠져나오고 MultiNum()함수가 끝날 무렵,
반환될 무렵에 control_Thread.Reset()로 설정해 더이상
 보내지는 신호가 없게 인식하도록 하였습니다.
실행해 보면 결과값입니다.
밑에 그림에서 //MyCalculator.control_Thread.Set()을 주석을 사용하였더니 
커맨드 창에 MyCalculator의 MultiNum()함수가 작동을 하는것을 알수있습니다.
왜 작동을 안할까요?? 위 그림 설명을 하면서 마지막 함수가 반환될 때
 control.Thread.Reset() 으로 되어있기 때문입니다.
주석을 지워보았습니다. 
동기화가 모가 되는거냐 라고 하실것 같습니다. 그래서 밑에 더 소스를 추가 해 보겠습니다.
밑에 노란줄있는 부분이 바뀐 소스입니다.
중간에 Thread.Sleep(2000)을 하여 2초간 잠시 모든 스레드가 멈추도록 하였습니다.
그후 다시 MyCalculator.control_Thread.Set()을 호출하여 신호상태를 바꿔났습니다.
결과 물입니다.왼 쪽 결과물은 Thread.Sleep(2000)이 불리기 전이고 
오른쪽은 Thread.Sleep(2000)이 불린뒤 입니다.

저작자 표시 비영리

posted by 방랑군 2012. 1. 21. 22:44
윈도우 프로그래밍을 자주 하지 않다보니 스레딩의 개념을 이해하고 까먹고의 연속이다.
이참에 CodeProject의 내용을 참고하여 간단히 AutoResetEvent와 ManualResetEvent의 용법을 정리해 보려 한다.

개요
공용리소스(파일/변수 등)을 멀티스레딩 환경에서 동시에 접근할 때 항상 고민해야 하는 문제는 바로 Access 문제이다. 이러한 골치아픈 문제를 해결하기 위해 여러가지 기법들이 있는데, 여기선 AutoResetEvent와 ManualResetEvent의 용법을 알아보도록 하겠다.

비유
AutoResetEvent와 ManualResetEvent는 마치 철도 건널목의 차단기와 같다고 보면 된다. 
당신이 신호를 보내면 차단기가 올라가기도 하고(Set), 다른 신호를 보내면 차단기가 내려가기도 한다.(Reset)
자동차가 차단기 앞에 도착했을때(WaitOne) 차단기의 신호상태에 따라 통과 여부를 판단하게 된다.

 
통과 신호를 받을때까지 대기하고 있다.

통과 신호를 받으면 통과하게 된다.


구현예제

1초 마다 이벤트를 발생시키는 Timer 객체를 이용하여 샘플 코드를 구현해 봤다.

아래 코드는 앞의 timer_Elapsed 코드가 완료되었는지에 상관없이 무조건 1초 마다 이벤트를 발생시킨다.

timer_Elapsed 코드 안에서는 랜덤하게 Sleep을 걸어 불규칙적인 프로세스 실행 시간을 시뮬레이션 하였다.


  1. using System;  
  2. using System.Threading;  
  3.   
  4. namespace TestMultiThreadLock  
  5. {  
  6.     class Program  
  7.     {  
  8.         static System.Timers.Timer timer;  
  9.         static Random rnd = new Random(1000);  
  10.           
  11.         static void Main(string[] args)  
  12.         {  
  13.             //1초에 한번씩 이벤트 발생  
  14.             timer = new System.Timers.Timer();  
  15.             timer.Interval = 1000;  
  16.             timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);  
  17.             timer.Start();  
  18.   
  19.             Console.ReadKey();  
  20.         }  
  21.   
  22.         static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)  
  23.         {  
  24.             DateTime curTime = DateTime.Now;  
  25.   
  26.             //임의의 프로세스 처리시간 대기  
  27.             int val = rnd.Next(0, 10000);  
  28.             Thread.Sleep(val);  
  29.   
  30.             Console.WriteLine(curTime.ToString("HH:mm:ss"));  
  31.         }  
  32.   
  33.     }  
  34. }  

실행결과는 아래와 같이 시간이 불규칙적으로 출력된다.


현재 코드는 단순 출력이지만 스레드에서 파일이나 for/foreach 문으로 종종 사용되는 Collection 객체에 억세스 했을 경우 심각한 예외상황이 발생할 가능성이 높아진다. (참고로 스레딩 안에서 발생되는 Exception은 바깥쪽 try/catch 구간에 잡히지 않은 채로 부모 프로세스마저 강제 종료되는 경우가 있으므로 스레딩 안쪽의 코드는 try/catch를 항상 구현하거나, 100% 신뢰 가능한 코드를 구현해야한다.)

따라서 위의 코드를 동기화, 즉 이벤트가 발생한 순서대로 실행하고, 후차로 진입한 함수는 앞선 함수가 끝날때 까지 대기시켜야 하는 방법을 ManualResetEvent로 해결해 보도록 한다.

  1. using System;  
  2. using System.Threading;  
  3.   
  4. namespace TestMultiThreadLock  
  5. {  
  6.     class Program  
  7.     {  
  8.         static ManualResetEvent mr = new ManualResetEvent(true);  
  9.         static System.Timers.Timer timer;  
  10.         static Random rnd = new Random(1000);  
  11.           
  12.         static void Main(string[] args)  
  13.         {  
  14.             //1초에 한번씩 이벤트 발생  
  15.             timer = new System.Timers.Timer();  
  16.             timer.Interval = 1000;  
  17.             timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);  
  18.             timer.Start();  
  19.   
  20.             Console.ReadKey();  
  21.         }  
  22.   
  23.         static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)  
  24.         {  
  25.             mr.WaitOne();  
  26.             mr.Reset();  
  27.   
  28.             DateTime curTime = DateTime.Now;  
  29.   
  30.             //임의의 프로세스 처리시간 대기  
  31.             int val = rnd.Next(0, 10000);  
  32.             Thread.Sleep(val);  
  33.   
  34.             Console.WriteLine(curTime.ToString("HH:mm:ss"));  
  35.   
  36.             mr.Set();  
  37.         }  
  38.   
  39.     }  
  40. }  

출력결과는 아래와 같다.


static ManualResetEvent mr = new ManualResetEvent(true);  
구문에서 초기값은 차단기가 내려간 상태의 여부를 결정한다.
true이면 차단기가 올라간 상태에서 시작되며, 
false이면 차단기가 내려간 상태에서 시작된다.


즉 위의 샘플에서는 차단기가 올라간 상태에서 시작되었으므로, 처음 실행되는 mr.WaitOne(); 구문은 지체없이 통과하게 된다.
mr.WaitOne(); 바로 다음의 mr.Reset();은 본인이 건널목을 통과하자마자 차단기를 다시 내리는 것을 의미한다.
(마치 엘리베이터 먼저 들어가서 홀랑 문닫고 자기만 올라가는 이미지를 생각하면 되겠다.)


mr.Reset(); 구문 부터 ~ mr.Set(); 구문이 실행 될 때 까지, 이후에 실행되는  timer_Elapsed 이벤트는 모두 mr.WaitOne(); 구문에서 대기하게 된다.


이러한 원리로 스레드를 동기화 시켜 시간을 순서대로 출력 할 수 있다.


AutoResetEvent와의 차이점

여기서 AutoResetEvent 와 ManualResetEvent의 차이점을 비교하자면, 단순히 WaitOne의 대기상태가 Set으로 인해 풀린 이후, 곧바로 Reset을 수동으로 하느냐 자동으로 하느냐의 차이밖에 없다.
위의 샘플코드에서는 WaitOne이후에 곧바로 Reset을 수동으로 하므로, 사실은 AutoResetEvent로 구현하여 Reset();  부분을 삭제하면 완전히 동일하게 동작하게 된다.
따라서 Reset 부분을 WaitOne 이후 어떠한 동작 이후에 실행해야 한다면 ManualResetEvent 클래스를 사용하면 된다.



스레드 동기화 시에 주의할 점

위의 샘플코드는 사실 스레드 동기화를 위해서는 적합하지 않은 코드이다. 굳이 위의 샘플코드를 작성한 이유는 스레드 동기화시 발생할 수 있는 문제점을 지적하기 위해서다.  
동기화된 샘플코드의 timer 객체는 정확히 1초마다 이벤트를 발생하는데 반해, timer_Elapsed 이벤트는 불규칙한 시간을 대기하게 된다. 


만약 대기시간이 100초가 걸린다면, 스레드는 최대 100개가 생성되므로 퍼포먼스에 문제를 일으키게 된다.
(물론 Timer 클래스 옵션에 AutoReset을 이용하면 동기적으로 timer_Elapsed 이벤트 자체가 발생되지 않게 구현 가능하다.)
즉, 스레드 동기화시엔 과다한 스레드가 생성되지 않게 유의해야 한다. 퍼포먼스로 인한 오류는 파악 자체가 매우 어려우므로 처음 부터 제대로 설계하는 것이 후세에(?) 도움이 됨을 유의하도록 하자.



참고

더욱 많은 스레드 동기화 기법 및 자세한 설명은 다음 사이트를 참고하면 많은 도움이 될 것이다.

posted by 방랑군 2012. 1. 21. 22:36

출처 :  http://jafm00n.tistory.com/40 

비관리 코드의 함수를 호출하기 위한, P/Invoke, 내보낸 함수의 프로토 타입을 정의할때면 매개변수로 넘겨 지거나 반환값으로 넘어오는 자료형들이 관리 코드의 자료형과 어울리지 않아 다소 혼란 스럽다. 그래서  플랫폼 호출 데이터 형식 에 맞게 자료형(LPTSTR의 경우 System.String으로)을 대입시켜 줘야 한다.

   그러나 그 외의 구조체, 구조체 포인터, 배열, 문자열의 다양한 형태등은 어떻게 대입시켜야 하는가? 이러한 형식들에 대해서는 특성과 자료형으로 잘 정리하여 적절한 구조를 만들어 대입시켜야 한다. 이러한 작업을 마샬링이라고 한다. 마샬링이라는 문자에 대한 이해 보다는 직접 코딩을 해서 그 자체를 이해 하는 것이 바람직하다고 생각한다.

  또한 비관리 코드로 전달되는 매개 변수에 대한 (In 혹은 Out과 같은) 방향 특성에 대한 설정은 어떻게 해야 하는지 고민해 봐야 할 것이다. 이에 대해서는 방향 특성을 참고 하기 바란다.
 

값으로

 

결과로

 

참조로

 

구조체에서 값으로

 

구조체에서 참조로(char*)

 

구조체에서 참조로(char[])

 

클래스에서 값으로(char*)

 

클래스에서 값으로(char[])

 

윽... 잠이 와서 도저히 못쓰겠다.{=,.=} ㅋ 공란은 내일 쓰기로 하고 ... 이만 자야 겠다.(2009-07-08 AM 3:24)

  ㅋㅋ 포스트를 쓰는데 장장 3일이 걸린것 같다. 나름 깔끔하게 정리하려고 노력 하였으나 지루해지고 고단해 지고 나른한 관계로 중간 중간에 무의 불 성실 하게 글을 올린 듯 하지만 ㅡㅡ;; 이렇게 까지 한 나 자신의 노고를 스스로 치하하는 바이다~ 끝~ (2009-07-09 PM 5:50)

------------------------------------------------------------------------------------------------------
 각주::=

  1. 문자열을 반복적으로 수정해야 하는 경우-루프 작업과 같은- String개체는 계속되는 새로 만드는 작업으로 인해 오버해드가 클 수 있다. 이를 대처하여 사용할 수 있는 것이 StringBuilder라고 한다. 또한 방향 특성이 다른 참조 타입 형식과는 달리 기본적으로 [in/out] 특성을 갖는다. 자세한 사항은 MSDN참조 [본문으로]
  2. MSDN: 문자열에 대한 기본 마샬링 [본문으로]
 
posted by 방랑군 2012. 1. 21. 22:34

출처 :  http://jafm00n.tistory.com/51

 다음 표에서는 Win32 API(Wtypes.h에 포함) 및 C 스타일 함수에서 사용되는 데이터 형식의 목록을 보여 줍니다. 
  관리되지 않는 대부분의 라이브러리에는 이러한 데이터 형식을 매개 변수를 통해 전달하고 값을 반환하는 함수가 포함되어 있습니다.
  세 번째 열에는 관리 코드에서 사용하는 .NET Framework 기본 제공 값 형식 또는 클래스가 표시되어 있습니다. 
  어떤 형식을 이 표에 나열된 동일한 크기의 다른 형식으로 대체할 수도 있습니다.

 

 Wtypes.h의
 관리되지 않는 형식
 관리되지 않는 
C 언어 형식
 관리되는 클래스 이름   설명 
 HANDLE  void*   System.IntPtr  32비트 Windows 운영 체제의 경우 32비트, 64비트 Windows 운영 체제의 경우 64비트 
 BYTE  unsigned char   System.Byte   8비트
 SHORT  short  System.Int16  16비트
 WORD  unsigned short  System.UInt16   16비트
 INT  int  System.Int32  32비트
 UINT  unsigned int  System.UInt32   32비트 
 LONG  long  System.Int32   32비트 
 BOOL  long  System.Int32   32비트 
 DWORD  unsigned long  System.UInt32   32비트 
 ULONG  unsigned long  System.UInt32    32비트
 CHAR  char  System.Char  ANSI로 데코레이트
 LPSTR  char*  System.String 또는
 System.Text.StringBuilder
 ANSI로 데코레이트
 LPCSTR  Const char*  System.String 또는
 System.Text.StringBuilder
 
 ANSI로 데코레이트
 LPWSTR  wchar_t*  System.String 또는
 System.Text.StringBuilder
 유니코드로 데코레이트
 LPCWSTR  Const wchar_t*  System.String 또는
 System.Text.StringBuilder
 
 유니코드로 데코레이트
 FLOAT  Float  System.Single  32비트
 DOUBLE  Double  System.Double  64비트

 
posted by 방랑군 2012. 1. 21. 22:31
 C#에서는 현재 응용프로그램이 실행중인 운영 체제에 있는 DLL의 함수를 플랫폼 호출(platform invoke)이라는 런타임 기능을 통해 호출할 수 있다.
  단순히 DllImport 어트리뷰트를 사용하여 DLL을 불러오면 된다.

MSDN



  다음 예제는 Win32API의 MessageBoxA함수를 사용하기 위해서 Windows DLL을 불러오는 간단한 콘솔 응용 프로그램이다. (물론 .NET의 System.Windows.Forms 네임스페이스에 MessageBox 클래스가 존재하고 이 것을 통해 활성화-Show-하는 방법이 존재한다.)

예제소스


  위의 응용 프로그램을 실행한 결과는 다음 그림에서 볼 수 있다.

.NET 런타임은 관리되는(managed) C# 코드에서 원본 DLL 함수까지 파라미터를 정렬시킨다. 그리고 MessageBox와 같은 메크로가 아닌 MessageBoxA나 MessageBoxW와 같은 실제 함수를 사용해야만 한다.

MSDN



  마지막으로 DllImport 어트리뷰트는 몇 가지 파라미터가 더 포함되어 있다.

DllImport 매개 변수


  런타임 시 관리되는(managed)코드에서 비관리(unmanaged) 코드까지 구조체를 올바르게 정렬시키려면 구조체 정의에 덧붙여 어트리뷰트를 선언해야 한다. 예를 들어, SystemTime구조체를 파라미터로 취하는 Win32 API 함수인 GetLocalTime을 선언할 수도 있다.

예제소스



 올바르게 정렬되는 구조체 파라미터의 경우에는 데이터가 선언된 대로 정확하게 정렬하는 것을 지정하는 StructLayout 어트리뷰트와 함께 선언해야 한다이런 방법을 사용하지 않는다면 데이터는 올바르게 정렬되지 않고 응용 프로그램은 오류가 발생할 것이다.

접기

        [StructLayout(LayoutKind.Sequential)]
        public class SystemTime {
            public ushort wYear;
            public ushort wMonth;
            public ushort wDayOfWeek;
            public ushort wDay;
            public ushort wHour;
            public ushort wMinute;
            public ushort wSecond;
            public ushort wMilliseconds;
        }

접기


다음과 같이 함수를 호출해 보자.

접기

        static void Main(string[] args)
        {
            SystemTime st = new SystemTime();
            GetLocalTime(st);
            string s = string.Format("date: {0}-{1}-{2}", st.wMonth, st.wDay, st.wYear);
            MessageBox(0, s, "Now", 0);                        
        }

접기



  위의 코드를 실행하면 다음 그림과 같은 대화 상자가 나타난다.



  또한 Win32 API 및 C 스타일 함수에서 사용되는 데이터 형식에 대하여 관리 코드에서 사용하는 .NET Framework 기본 제공 값 형식 또는 클래스로 대치 시켜 줘야 한다. 그에 대한 내용은 다음 링크를 참조! ^^
2009/07/06 - [Programming/C#] - 플랫폼 호출 데이터 형식



참고문헌: Inside C#

'강좌 > C#' 카테고리의 다른 글

_문자열 마샬링  (0) 2012.01.21
_플랫폼 호출 데이터 형식  (0) 2012.01.21
16진수 문자열 변환  (0) 2012.01.21
VB.NET and C# 의 비교문서  (0) 2012.01.21
C# 으로 만든 DLL asp에서 사용  (0) 2012.01.21
posted by 방랑군 2012. 1. 21. 22:09

이 예제에서는 string에 있는 각 문자의 16진수 값을 출력합니다. 먼저 string을 문자 배열로 구문 분석합니다. 그런 다음 각 문자에 대해 ToInt32(Char)를 호출하여 해당 숫자 값을 가져옵니다. 마지막으로 이 숫자를 16진수 형식으로 string에 나타냅니다.


C#
string input = "Hello World!";
char[] values = input.ToCharArray();
foreach (char c in values)
{
    // Get the integral value of the character.
    int value = Convert.ToInt32(c);
    // Convert the decimal value to a hexadecimal value in string form.
    string hex = String.Format("{0:X}", value);
    Console.WriteLine("Hexadecimal value of {0} is {1}", c, hex);
}

Hexadecimal value of H is 48
Hexadecimal value of e is 65
Hexadecimal value of l is 6C
Hexadecimal value of l is 6C
Hexadecimal value of o is 6F
Hexadecimal value of   is 20
Hexadecimal value of W is 57
Hexadecimal value of o is 6F
Hexadecimal value of r is 72
Hexadecimal value of l is 6C
Hexadecimal value of d is 64
Hexadecimal value of ! is 21

이 예제에서는 16진수 값의 string을 구문 분석하고 각 16진수 값에 해당하는 문자를 출력합니다. 먼저Split(array<Char>[]()[]) 메서드를 호출하여 각 16진수 값을 배열의 개별 string으로 가져옵니다. 그런 다음ToInt32(String, Int32)를 호출하여 16진수 값을 int로 표현되는 10진수로 변환합니다. 이 예제에서는 문자 코드에 해당하는 문자를 가져오는 두 가지 방법을 보여 줍니다. 첫 번째 방법에서는 정수 인수에 해당하는 문자를 string으로 반환하는 ConvertFromUtf32(Int32)를 사용합니다. 두 번째 방법에서는 int를 char로 명시적으로 캐스팅합니다.

string hexValues = "48 65 6C 6C 6F 20 57 6F 72 6C 64 21";
string[] hexValuesSplit = hexValues.Split(' ');
foreach (String hex in hexValuesSplit)
{
    // Convert the number expressed in base-16 to an integer.
    int value = Convert.ToInt32(hex, 16);
    // Get the character corresponding to the integral value.
    string stringValue = Char.ConvertFromUtf32(value);
    char charValue = (char)value;
    Console.WriteLine("hexadecimal value = {0}, int value = {1}, char value = {2} or {3}", hex, value, stringValue, charValue);
}

hexadecimal value = 48, int value = 72, char value = H or H
hexadecimal value = 65, int value = 101, char value = e or e
hexadecimal value = 6C, int value = 108, char value = l or l
hexadecimal value = 6C, int value = 108, char value = l or l
hexadecimal value = 6F, int value = 111, char value = o or o
hexadecimal value = 20, int value = 32, char value =   or
hexadecimal value = 57, int value = 87, char value = W or W
hexadecimal value = 6F, int value = 111, char value = o or o
hexadecimal value = 72, int value = 114, char value = r or r
hexadecimal value = 6C, int value = 108, char value = l or l
hexadecimal value = 64, int value = 100, char value = d or d
hexadecimal value = 21, int value = 33, char value = ! or !

이 예제에서는 Parse(String, NumberStyles) 메서드를 호출하여 16진수 string을 정수로 변환하는 다른 방법을 보여 줍니다.

string hexString = "8E2";
int num = Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
Console.WriteLine(num);



출처: http://msdn.microsoft.com/ko-kr/library/bb311038.aspx
posted by 방랑군 2012. 1. 21. 21:55

VB.NET and C# Comparison
This is a quick reference guide to highlight some key syntactical differences between VB.NETand C#. Hope you find this useful!
Thank you to Tom Shelton, Fergus Cooney, and others for your input. 
Also see Java and C# Comparison.





VB.NET

C#

Comments
' Single line only
Rem Single line only

// Single line
/* Multiple
    line  */
/// XML comments on single line
/** XML comments on multiple lines */

Data Types

Value Types
Boolean
Byte
Char   (example: "A"c)
Short, Integer, Long
Single, Double
Decimal
Date

Reference Types
Object
String

Dim x As Integer 
Console.WriteLine(x.GetType())     ' Prints System.Int32 
Console.WriteLine(TypeName(x))  ' Prints Integer

' Type conversion
Dim d As Single = 3.5 
Dim i As Integer = CType(d, Integer)   ' set to 4 (Banker's rounding)
i = CInt(d)  ' same result as CType
i = Int(d)    ' set to 3 (Int function truncates the decimal)

Value Types
bool
byte, sbyte
char   (example: 'A')
short, ushort, int, uint, long, ulong
float, double
decimal
DateTime   (not a built-in C# type)

Reference Types
object
string

int x;
Console.WriteLine(x.GetType());    // Prints System.Int32
Console.WriteLine(typeof(int));      // Prints System.Int32


// Type conversion
 
float d = 3.5f; 
int i = (int) d;   // set to 3  (truncates decimal)

Constants
Const MAX_STUDENTS As Integer = 25

' Can be set to a const or a variable. May be initialized in a constructor. 
ReadOnly MIN_DIAMETER As Single = 4.93

const int MAX_STUDENTS = 25;

// Can be set to a const or a variable. May be initialized in a constructor. 
readonly float MIN_DIAMETER = 4.93f;

Enumerations
Enum Action 
  Start 
  [Stop]   ' Stop is a reserved word
  Rewind 
  Forward 
End Enum 

Enum Status 
  Flunk = 50 
  Pass = 70 
  Excel = 90 
End Enum

Dim a As Action = Action.Stop 
If a <> Action.Start Then _ 
   Console.WriteLine(a.ToString & " is " & a)    ' Prints "Stop is 1" 

Console.WriteLine(Status.Pass)     ' Prints 70 
Console.WriteLine(Status.Pass.ToString())     ' Prints Pass
enum Action {Start, Stop, Rewind, Forward};
enum Status {Flunk = 50, Pass = 70, Excel = 90};

Action a = Action.Stop;
if (a != Action.Start)
  Console.WriteLine(a + " is " + (int) a);    // Prints "Stop is 1"

Console.WriteLine((int) Status.Pass);    // Prints 70 
Console.WriteLine(Status.Pass);      // Prints Pass
Operators

Comparison
=  <  >  <=  >=  <>

Arithmetic
+  -  *  /
Mod
\  (integer division)
^  (raise to a power)

Assignment
=  +=  -=  *=  /=  \=  ^=  <<=  >>=  &=

Bitwise
And  AndAlso  Or  OrElse  Not  <<  >>

Logical
And  AndAlso  Or  OrElse  Not

Note: AndAlso and OrElse are for short-circuiting logical evaluations

String Concatenation
&

Comparison
==  <  >  <=  >=  !=

Arithmetic
+  -  *  /
%  (mod)
/  (integer division if both operands are ints)
Math.Pow(x, y)

Assignment
=  +=  -=  *=  /=   %=  &=  |=  ^=  <<=  >>=  ++  --

Bitwise
&  |  ^   ~  <<  >>

Logical
&&  ||   !

Note: && and || perform short-circuit logical evaluations

String Concatenation
+

Choices

greeting = IIf(age < 20, "What's up?", "Hello")

' One line doesn't require "End If", no "Else"
If language = "VB.NET" Then langType = "verbose"

' Use : to put two commands on same line
If x <> 100 And y < 5 Then x *= 5 : y *= 2  

' Preferred
If x <> 100 And y < 5 Then
  x *= 5 
  y *= 2
End If

' or to break up any long single command use _
If whenYouHaveAReally < longLine And itNeedsToBeBrokenInto2 > Lines Then _
  UseTheUnderscore(charToBreakItUp)

'If x > 5 Then 
  x *= y 
ElseIf x = 5 Then 
  x += y 
ElseIf x < 10 Then 
  x -= y 
Else 
  x /= y 
End If

Select Case color   ' Must be a primitive data type
  Case "pink", "red"
    r += 1 
  Case "blue" 
    b += 1 
  Case "green" 
    g += 1 
  Case Else 
    other += 1 
End Select

greeting = age < 20 ? "What's up?" : "Hello";





if (x != 100 && y < 5) {    // Multiple statements must be enclosed in {}
  x *= 5;
  y *= 2;
}

No need for _ or : since ; is used to terminate each statement.







if
 (x > 5) 
  x *= y; 
else if (x == 5) 
  x += y; 
else if (x < 10) 
  x -= y; 
else 
  x /= y;



switch (color) {                          // Must be integer or string
  case "pink":
  case "red":    r++;    break;        // break is mandatory; no fall-through
  case "blue":   b++;   break;
  case "green": g++;   break;
  default:    other++;   break;       // break necessary on default
}

Loops
Pre-test Loops:
While c < 10 
  c += 1 
End While

Do Until c = 10 
  c += 1 
Loop

Do While c < 10 
  c += 1 
Loop

For c = 2 To 10 Step 2
  Console.WriteLine(c) 
Next


Post-test Loops:
Do 
  c += 1 
Loop While c < 10
Do 
  c += 1 
Loop Until c = 10

'  Array or collection looping
Dim names As String() = {"Fred", "Sue", "Barney"} 
For Each s As String In names 
  Console.WriteLine(s) 
Next

Pre-test Loops:  

// no "until" keyword
while (i < 10) 
  i++;

for (i = 2; i < = 10; i += 2) 
  Console.WriteLine(i);



Post-test Loop:

do 
  i++; 
while (i < 10);



// Array or collection looping
string[] names = {"Fred", "Sue", "Barney"};
foreach (string s in names)
  Console.WriteLine(s);

Arrays

Dim nums() As Integer = {1, 2, 3} 
For i As Integer = 0 To nums.Length - 1 
  Console.WriteLine(nums(i)) 
Next 

' 4 is the index of the last element, so it holds 5 elements
Dim names(4) As String 
names(0) = "David"
names(5) = "Bobby"  ' Throws System.IndexOutOfRangeException 

' Resize the array, keeping the existing values (Preserve is optional)
ReDim Preserve names(6)



Dim twoD(rows-1, cols-1) As Single 
twoD(2, 0) = 4.5

Dim jagged()() As Integer = { _ 
  New Integer(4) {}, New Integer(1) {}, New Integer(2) {} } 
jagged(0)(4) = 5

int[] nums = {1, 2, 3};
for (int i = 0; i < nums.Length; i++)
  Console.WriteLine(nums[i]);


// 5 is the size of the array
string[] names = new string[5];
names[0] = "David";
names[5] = "Bobby";   // Throws System.IndexOutOfRangeException 


// C# can't dynamically resize an array.  Just copy into new array.
string[] names2 = new string[7]; 
Array.Copy(names, names2, names.Length);   // or names.CopyTo(names2, 0); 

float[,] twoD = new float[rows, cols];
twoD[2,0] = 4.5f; 

int[][] jagged = new int[3][] { 
  new int[5], new int[2], new int[3] };
jagged[0][4] = 5;

Functions

' Pass by value (in, default), reference (in/out), and reference (out)  
Sub TestFunc(ByVal x As Integer, ByRef y As Integer, ByRef z As Integer)
  x += 1
  y += 1 
  z = 5 
End Sub

Dim a = 1, b = 1, c As Integer   ' c set to zero by default  
TestFunc(a, b, c) 
Console.WriteLine("{0} {1} {2}", a, b, c)   ' 1 2 5

' Accept variable number of arguments 
Function Sum(ByVal ParamArray nums AsInteger()) As Integer 
  Sum = 0  
  For Each i As Integer In nums 
    Sum += i 
  Next 
End Function   ' Or use Return statement like C#

Dim total As Integer = Sum(4, 3, 2, 1)   ' returns 10

' Optional parameters must be listed last and must have a default value 
Sub SayHello(ByVal name As String, OptionalByVal prefix As String = "")
  Console.WriteLine("Greetings, " & prefix & " " & name) 
End Sub

SayHello("Strangelove", "Dr.")
SayHello("Madonna")

// Pass by value (in, default), reference (in/out), and reference (out)
void TestFunc(int x, ref int y, out int z) {
  x++;  
  y++;
  z = 5;
}

int a = 1, b = 1, c;  // c doesn't need initializing
TestFunc(a, ref b, out c);
Console.WriteLine("{0} {1} {2}", a, b, c);  // 1 2 5

// Accept variable number of arguments
int Sum(params int[] nums) {
  int sum = 0;
  foreach (int i in nums)
    sum += i;
  return sum;
}

int total = Sum(4, 3, 2, 1);   // returns 10

/* C# doesn't support optional arguments/parameters.  Just create two different versions of the same function. */  
void SayHello(string name, string prefix) {
  Console.WriteLine("Greetings, " + prefix + " " + name);


void SayHello(string name) { 
  SayHello(name, ""); 
}

Exception Handling

' Deprecated unstructured error handling
On Error GoTo MyErrorHandler
...
MyErrorHandler: Console.WriteLine(Err.Description)

Dim ex As New Exception("Something is really wrong.") 
Throw  ex 

Try 
  y = 0
  x = 10 / y
Catch ex As Exception When y = 0 ' Argument and When is optional
  Console.WriteLine(ex.Message) 
Finally 
  Beep() 
End Try





Exception up = new Exception("Something is really wrong."); 
throw up;  // ha ha

try { 
  y = 0; 
  x = 10 / y; 

catch (Exception ex) {   // Argument is optional, no "When" keyword 
  Console.WriteLine(ex.Message); 

finally { 
  // Must use unmanaged MessageBeep API function to beep 
}

Namespaces

Namespace Harding.Compsci.Graphics 
  ...
End Namespace

' or

Namespace Harding 
  Namespace Compsci 
    Namespace Graphics 
      ...
    End Namespace 
  End Namespace 
End Namespace

Imports Harding.Compsci.Graphics

namespace Harding.Compsci.Graphics {
  ...
}

// or

namespace Harding {
  namespace Compsci {
    namespace Graphics {
      ...
    }
  }
}

using Harding.Compsci.Graphics;

Classes / Interfaces

Accessibility keywords 
Public
Private
Friend                    
Protected
Protected Friend
Shared

' Inheritance
Class FootballGame
  Inherits Competition
  ...
End Class 

' Interface definition
Interface IAlarmClock 
  ...
End Interface

// Extending an interface 
Interface IAlarmClock 
  Inherits IClock
  ...
End Interface

// Interface implementation
Class WristWatch 
  Implements IAlarmClock, ITimer 
   ...
End Class 

Accessibility keywords 
public
private
internal
protected
protected internal
static

// Inheritance
class FootballGame : Competition {
  ...
}


// Interface definition

interface IAlarmClock {
  ...
}

// Extending an interface 
interface IAlarmClock : IClock {
  ...
}


// Interface implementation

class WristWatch : IAlarmClock, ITimer {
   ...
}

Constructors / Destructors
Class SuperHero
  Private _powerLevel As Integer 

  Public Sub New() 
    _powerLevel = 0 
  End Sub 

  Public Sub New(ByVal powerLevel As Integer)
    Me._powerLevel = powerLevel 
  End Sub

  Protected Overrides Sub Finalize() 
   ' Desctructor code to free unmanaged resources 
    MyBase.Finalize() 
  End Sub
End Class

class SuperHero {
  private int _powerLevel;

  public SuperHero() {
     _powerLevel = 0;
  }

  public SuperHero(int powerLevel) {
    this._powerLevel= powerLevel; 
  }

  ~SuperHero() {
    // Destructor code to free unmanaged resources.
    // Implicitly creates a Finalize method

  }
}

Objects

Dim hero As SuperHero = New SuperHero 
With hero 
  .Name = "SpamMan" 
  .PowerLevel = 3 
End With 

hero.Defend("Laura Jones") 
hero.Rest()     ' Calling Shared method
' or
SuperHero.Rest()

Dim hero2 As SuperHero = hero  ' Both refer to same object 
hero2.Name = "WormWoman" 
Console.WriteLine(hero.Name)   ' Prints WormWoman

hero = Nothing    ' Free the object

If hero Is Nothing Then _ 
  hero = New SuperHero

Dim obj As Object = New SuperHero 
If TypeOf obj Is SuperHero Then _
  Console.WriteLine("Is a SuperHero object.")

SuperHero hero = new SuperHero(); 

// No "With" construct
hero.Name = "SpamMan"; 
hero.PowerLevel = 3;

hero.Defend("Laura Jones");
SuperHero.Rest();   // Calling static method



SuperHero hero2 = hero;   // Both refer to same object 
hero2.Name = "WormWoman"; 
Console.WriteLine(hero.Name);   // Prints WormWoman

hero = null ;   // Free the object

if (hero == null)
  hero = new SuperHero();

Object obj = new SuperHero(); 
if (obj is SuperHero) 
  Console.WriteLine("Is a SuperHero object.");

Structs

Structure StudentRecord 
  Public name As String 
  Public gpa As Single 

  Public Sub New(ByVal name As String, ByVal gpa As Single) 
    Me.name = name 
    Me.gpa = gpa 
  End Sub 
End Structure

Dim stu As StudentRecord = New StudentRecord("Bob", 3.5) 
Dim stu2 As StudentRecord = stu   

stu2.name = "Sue" 
Console.WriteLine(stu.name)    ' Prints Bob 
Console.WriteLine(stu2.name)  ' Prints Sue

struct StudentRecord {
  public string name;
  public float gpa;

  public StudentRecord(string name, float gpa) {
    this.name = name;
    this.gpa = gpa;
  }
}

StudentRecord stu = new StudentRecord("Bob", 3.5f);
StudentRecord stu2 = stu;  

stu2.name = "Sue";
Console.WriteLine(stu.name);    // Prints Bob
Console.WriteLine(stu2.name);   // Prints Sue

Properties

Private _size As Integer

Public Property Size() As Integer
  Get 
    Return _size 
  End Get 
  Set (ByVal Value As Integer) 
    If Value < 0 Then 
      _size = 0 
    Else 
      _size = Value 
    End If 
  End Set 
End Property

foo.Size += 1

private int _size;

public int Size { 
  get { 
    return _size; 
  } 
  set { 
    if (value < 0) 
      _size = 0; 
    else 
      _size = value; 
  } 
}


foo.Size++;

Delegates / Events

Delegate Sub MsgArrivedEventHandler(ByVal message As String)

Event MsgArrivedEvent As MsgArrivedEventHandler

' or to define an event which declares a delegate implicitly
Event MsgArrivedEvent(ByVal message As String)

AddHandler MsgArrivedEvent, AddressOfMy_MsgArrivedCallback 
' Won't throw an exception if obj is Nothing
RaiseEvent MsgArrivedEvent("Test message")
RemoveHandler MsgArrivedEvent,AddressOf My_MsgArrivedCallback

Imports System.Windows.Forms

Dim WithEvents MyButton As Button   ' WithEvents can't be used on local variable
MyButton = New Button

Private Sub MyButton_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) HandlesMyButton.Click 
  MessageBox.Show(Me, "Button was clicked", "Info", _
    MessageBoxButtons.OK, MessageBoxIcon.Information) 
End Sub

delegate void MsgArrivedEventHandler(string message);

event MsgArrivedEventHandler MsgArrivedEvent;

// Delegates must be used with events in C#


MsgArrivedEvent += new MsgArrivedEventHandler(My_MsgArrivedEventCallback);
MsgArrivedEvent("Test message");    // Throws exception if obj is null
MsgArrivedEvent -= new MsgArrivedEventHandler(My_MsgArrivedEventCallback);



using System.Windows.Forms;

Button MyButton = new Button(); 
MyButton.Click += new System.EventHandler(MyButton_Click);

private void MyButton_Click(object sender, System.EventArgs e) { 
  MessageBox.Show(this, "Button was clicked", "Info", 
    MessageBoxButtons.OK, MessageBoxIcon.Information); 
}

Console I/O

Special character constants
vbCrLf, vbCr, vbLf, vbNewLine 
vbNullString 
vbTab 
vbBack 
vbFormFeed 
vbVerticalTab
"" 
Chr(65)  ' Returns 'A'

Console.Write("What's your name? ") 
Dim name As String = Console.ReadLine() 
Console.Write("How old are you? ") 
Dim age As Integer = Val(Console.ReadLine()) 
Console.WriteLine("{0} is {1} years old.", name, age)  
' or 
Console.WriteLine(name & " is " & age & " years old.") 

Dim c As Integer 
c = Console.Read()    ' Read single char 
Console.WriteLine(c)   ' Prints 65 if user enters "A"

Escape sequences
\n, \r
\t
\\
\"

Convert.ToChar(65)  // Returns 'A' - equivalent to Chr(num) in VB
// or

(char) 65

Console.Write("What's your name? ");
string name = Console.ReadLine();
Console.Write("How old are you? ");
int age = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("{0} is {1} years old.", name, age);
// or
Console.WriteLine(name + " is " + age + " years old.");


int c = Console.Read();  // Read single char
Console.WriteLine(c);    // Prints 65 if user enters "A"

File I/O

Imports System.IO

' Write out to text file
Dim writer As StreamWriter = File.CreateText("c:\myfile.txt") 
writer.WriteLine("Out to file.") 
writer.Close()

' Read all lines from text file
Dim reader As StreamReader = File.OpenText("c:\myfile.txt") 
Dim line As String = reader.ReadLine() 
While Not line Is Nothing 
  Console.WriteLine(line) 
  line = reader.ReadLine() 
End While 
reader.Close()

' Write out to binary file
Dim str As String = "Text data" 
Dim num As Integer = 123 
Dim binWriter As NewBinaryWriter(File.OpenWrite("c:\myfile.dat"))  
binWriter.Write(str)  
binWriter.Write(num) 
binWriter.Close()

' Read from binary file
Dim binReader As NewBinaryReader(File.OpenRead("c:\myfile.dat"))
str = binReader.ReadString() 
num = binReader.ReadInt32() 
binReader.Close()

using System.IO;

// Write out to text file
StreamWriter writer = File.CreateText("c:\\myfile.txt");
writer.WriteLine("Out to file."); 
writer.Close();

// Read all lines from text file
StreamReader reader = File.OpenText("c:\\myfile.txt"); 
string line = reader.ReadLine(); 
while (line != null) {
  Console.WriteLine(line); 
  line = reader.ReadLine(); 

reader.Close();

// Write out to binary file
string str = "Text data"; 
int num = 123; 
BinaryWriter binWriter = new BinaryWriter(File.OpenWrite("c:\\myfile.dat")); 
binWriter.Write(str); 
binWriter.Write(num); 
binWriter.Close();

// Read from binary file
BinaryReader binReader = new BinaryReader(File.OpenRead("c:\\myfile.dat")); 
str = binReader.ReadString(); 
num = binReader.ReadInt32(); 
binReader.Close();

 

 

발췌 : http://www.harding.edu

posted by 방랑군 2012. 1. 21. 21:36

[C# 으로 만든 DLL asp에서 사용]

- C#으로 만든 base64 암호화 및 복호화 함수 생성후 asp 에서 사용

- 파일 첨부함.

 

☞ C# 클래스라이브러리 프로젝트 생성 - ComPlusExample

 

 

☞ System.EnterpriseSevices 참조추가

 

☞ AssemblyInfo.cs 수정

[assembly: ComVisible(false)] 를 [assembly: ComVisible(true)]로 변경

 

 

☞ ComPlusClass 클래스 파일추가

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.EnterpriseServices;
[assembly: ApplicationName("ComPlusExample")]
[assembly: Description("Complus Assembly")]
[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationAccessControl(false)]

namespace ComPlusExample
{
    [EventTrackingEnabled(true)]
    [Description("Interface Serviced Component")]
    public class ComPlusClass : ServicedComponent
    {
        public string Base64Encode(string str)
        {
            byte[] byt = System.Text.Encoding.UTF8.GetBytes(str);

            return Convert.ToBase64String(byt);
        }

        public string Base64Decode(string str)
        {
            byte[] byt = Convert.FromBase64String(str);

            return System.Text.Encoding.UTF8.GetString(byt);
        }
    }
}

 

 

☞  강력한 이름 키 만들기(프로젝트 오른클릭 속성클릭)

- 서명탭 -> 어셈블리 서명 체크 -> 새로만들기


 

- 키 파일 이름 : ComPlusExample -> 체크박스 해제 -> 확인

 

 

☞ 저장 및 빌드

 

 

☞ Visual Studio 2008 명령 프롬프트를 이용한 등록

- 빌드후 dll이 있는 곳에서 등록 (프로젝트경로\bin\Debug\ComPlusExample.dll)

regsvcs ComPlusExample.dll
regasm ComPlusExample.dll

 


☞ COM+ 응용 프로그램 등록확인

 



☞ test.asp 실행

 <%

set Com = server.createobject("ComPlusExample.ComPlusClass")
encodeStr = Com.Base64Encode("홍길동")
Response.Write "암호화 : " & encodeStr & "<br/>"
Response.Write "복호화 : " & Com.Base64Decode(encodeStr) & "<br/>"

%>

 

 

☞ 결과

 

posted by 방랑군 2012. 1. 21. 21:27
C#을 다루다보면 간혹 응용 프로그램의 중복 실행을 방지해야하는 경우가 있습니다.

특히, 소켓 프로그램의 경우 중복 실행이 될 경우 포트 충돌 등으로 오류가 발생할 소지가 있어 프로그램 실행시 중복 실행을 방지하는 알고리즘은 필수라고 생각이 됩니다.

필자의 경우는 제작한 프로그램이 트래이 아이콘에 등록되다 보니 사용자들이 간혹 실수로 프로그램을 다시 실행하는 경우가 종종 있어서 Mutex를 사용하여 중복실행을 방지하고 있습니다.

프로세스를 찾아서 하는 방식도 있지만 여기서 Mutex를 이용하는 방법을 소개하고자 합니다.

Mutex 개념
    Mutex는 스레드 동기화의 한 방식으로 공유 리소스를 하나의 스레드가 단독으로 액세스할 수 있도록 합니다. 즉, 스레드가 뮤텍스를 가져오면 첫 번째 스레드가 뮤텍스를 해제할 때까지 해당 뮤텍스를 가져오려는 두 번째 스레드는 일시 중단(대기)됩니다.

중복 실행 방지 원리
    중복 실행 방지의 경우는 호출한 스레드가 초기 소유권를 가지도록 설정하여 Mutex 생성시 초기 소유권이 부여되었는지의 여부에 따라 실행과 중단을 결정합니다.

  • 소유권이 부여된 경우라면 사용중인 스레드가 없으므로 프로그램 가동
  • 소유권이 부여되지 않은 경우라면 이미 다른 스레드가 사용 중이므로 프로그램 종료

각 방식에 따라 장단점이 있지만 Mutex의 경우 간결하고 코드가 짧아 프로그램에 좋을 듯 합니다.
  • Mutex를 사용하기 위해서는 System.Threading 네임 스페이스를 추가합니다.
  • Main함수에 알고리즘을 구현합니다.

1. Mutex 함수 설명


    Name Space

    • System.Threading

      public Mutex(	bool initiallyOwned,	string name,	out bool createdNew  )
    Parameters
    • bool initiallyOwned : 호줄하는 쓰레드가 뮤텍스의 초기 소유권을 갖는지를 지정
    • string name : 뮤텍스 이름
    • out bool createdNew : 소유권 부여 여부

2. C# 프로그램 코드


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//Program.CS
//namespace에 아래 추가
using System.Threading;
[STAThread]
static void Main()
{
// 기존 코드 주석 처리
//Application.EnableVisualStyles();
//Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
bool bNew;
Mutex mutex = new Mutex(true, "MutexName", out bNew);
if(bNew)
{
// 소유권이 부여
// 즉 해당 프로그램이 실행되고 있지 않은 경우
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
// 뮤텍스 릴리즈
mutex.ReleaseMutex();
}
else
{
// 소유권이 부여되지 않음
MessageBox.Show("이미실행중입니다.");
Application.Exit();
}
}
C# 프로그램 중복 실행 방지 Mutex / Using a mutex to prevent multiple application from running
http://all4cs.tistory.com - 두그미의 사는 이야기

'강좌 > C#' 카테고리의 다른 글

VB.NET and C# 의 비교문서  (0) 2012.01.21
C# 으로 만든 DLL asp에서 사용  (0) 2012.01.21
.Net single-instance application without activation  (0) 2012.01.21
C# 사운드 재생  (1) 2012.01.21
SELECT 함수  (0) 2012.01.19
posted by 방랑군 2012. 1. 21. 21:22

기본적으로 .net과 C# 기반이면서,

  1. 하나의 인스턴스만을 허용하고
  2. (추가)실행시 포커스를 가져가지 않는 어플리케이션 개발! 
    창이 위로 뜨거나 작업표시줄이 번쩍거려서는 곤란하다.

메신저나 팝업 알림창 뭐 이런 용도로 필요할 듯하다. 내 경우 선거방송과 관련해서 백그라운드로 데이터를 업데이트해주는 유틸을 개발하기 위해 필요했다. 백그라운드로 뜬다지만 UI를 없앨 수는 없고, 번쩍대지 않고 뒤에 조용히 떠있으면 되는 그런 유틸이다.

이것은 쉬워 보이지만 막상 해보면 어렵다.
1의 single-instance app이란 것은 여러 가지 솔루션들이 나와 있고 그 중에 명령줄인수를 받을 수 있는 것으로는 visual basic으로부터 WindowsFormsApplicationBase를 가져다 쓰는 방법이 가장 쉽다.
코드프로젝트에 설명이 잘 돼있으면서 데모프로젝트까지 제공하고 있는 포스트가 있다.
http://www.codeproject.com/KB/cs/CSSIApp.aspx

2의포커스를 훔쳐가지 않기, 즉 "without activation" 이것도 쉽다.
Form의 ShowWithoutActivation 속성을 true로 설정하면 된다. read-only이기 때문에 다음과 같이 재정의하면 된다.

  protected override bool ShowWithoutActivation
  {
   get { return true; }
  }

그러나, 실제로 해보면 작동하지 않는다.
ShowWithoutActivation은 분명히 true로 설정되어 있음을 form 생성 후에도 확인할 수 있지만, 매번 실행시마다 창은 작업중이던 다른 창 위로 뜨고 포커스도 빼앗겼다.
어쩌다 창이 위로 뜨지 않는 경우도 생겼지만, 어쨌든 태스크바는 대화를 원하는 메신저 창처럼 마구 번쩍인다.

두 개의 서로 다른 문제에 대해서 각각 솔루션들은 넘쳐나지만 둘 다를 해결해주는 방법은 없었다. 시계는 어느새 11시 30분을 넘기고... 이제는 포기하고 싶은 마음 생길 때 쯤에 울리는 전화벨 소리~ 는 아니고 뭔가를 보았다.

그것은 visual basic 응용 프로그램 모델 개요라는 MSDN 아티클을 보고 있을 때였다. 내용은 이런 것이었다.
Visual Basic 응용 프로그램 모델을 사용하면 단일 인스턴스 응용 프로그램을 쉽게 만들 수 있습니다. 단일 인스턴스 응용 프로그램은 응용 프로그램 인스턴스를 한 번에 하나씩만 실행할 수 있다는 점에서 일반 응용 프로그램과 다릅니다. 단일 인스턴스 응용 프로그램에서 다른 인스턴스를 추가로 시작하려고 하면 원래 실행 중이던 인스턴스는 StartupNextInstance 이벤트를 통해 다른 시작이 시도되었다는 알림을 받게 됩니다. 이 알림에는 후속 인스턴스의 명령줄 인수가 포함됩니다. 그러면 응용 프로그램의 후속 인스턴스는 초기화가 실행되기 전에 닫힙니다.

단일 인스턴스 응용 프로그램은 시작될 때 자신이 응용 프로그램의 첫 번째 인스턴스인지 후속 인스턴스인지 확인합니다.

  • 첫 번째 인스턴스이면 정상적으로 시작됩니다.

  • 첫 번째 인스턴스가 실행되고 있는 동안 응용 프로그램을 시작하려는 시도가 이루어지면 그때마다 결과 동작은 매우 달라집니다. 후속 시도는 첫 번째 인스턴스에 명령줄 인수에 대해 알린 다음 즉시 종료됩니다. 첫 번째 인스턴스는 StartupNextInstance 이벤트를 처리하여 후속 인스턴스의 명령줄 인수가 무엇인지 확인한 다음 계속 실행됩니다.

    이 다이어그램은 후속 인스턴스에서 첫 번째 인스턴스에 신호하는 방법을 보여 줍니다.

StartupNextInstance 이벤트를 처리하여 단일 인스턴스 응용 프로그램이 동작하는 방식을 제어할 수 있습니다. 예를 들어, Microsoft Outlook은 일반적으로 단일 인스턴스 응용 프로그램으로 실행됩니다. Outlook이 실행되고 있을 때 Outlook을 다시 시작하려고 하면 포커스가 원래 인스턴스로 변경되고 다른 인스턴스는 열리지 않습니다.

음... 그런 것인가.
첫번째 인스턴스는 Startup, 그 다음부터는 StartupNextInstance 이벤트가 발생한다.
음 그래 StartupNextInstance... (이미 의식이 혼미한 상태)
전에는 기본 형식의 메서드를 더블클릭하면 자동으로 오버라이드가 됐던 것 같은데 왜 안 되는거야...
visual studio의 개체 브라우저를 하염없이 클릭만 하고 있다가...

헉!

"응용프로그램 인스턴스를 포그라운드로 가져와야 하는지"

저 구절이 눈에 번쩍 하고 띄었다.
그렇다... 이거 한 줄만 StartupNextInstance 이벤트 핸들러에 추가하면 된다.
eventArgs.BringToForeground = false;

원래부터 WindowsFormsApplicationBase에서는 지원하고 있었던 거였다. 이렇게 허무할 데가... 오늘 검색한 페이지만 해도 수백 개는 될텐데 ㅜㅜ
그렇지만 어쨌든 오늘 내로 해결해서 다행이라고 생각하는 양고였습니다.
posted by 방랑군 2012. 1. 21. 21:21

// Managed DirectX의 AudioVideoPlayback을 이용하는 방법이 있습니다.

using Microsoft.DirectX.AudioVideoPlayback; // 참조에 Microsoft.DirectX.AudioVideoPlayback 추가

 

namespace WindowsApplication1
{
 public partial class Form1 : Form
 {

  Audio _music = null;
  Audio _sound = null;
  public Form1()
  {
   InitializeComponent();
   string music = @"음악 파일";
   string sound= @"사운드 파일";
   

   _music = new Audio(music);
   
   _music.Play(); // 배경 음악 파일 플레이

   _sound = new Audio(sound);   
  }

  private void button1_Click(object sender, EventArgs e)
  {
   if (!_sound.Stopped) // 사운드가 끝나지 않은 경우, Stop을 해준다.
    _sound.Stop();
   _sound.Play();

  
  }
 }
}

posted by 방랑군 2012. 1. 21. 14:49
ebXML [e-business Extensible Markup Language]
ebXML 정의
-      전자상거래 데이터 교환 표준을 마련하고자 하는 전세계적 프로젝트
-      XML 기반으로 e-business 가능하게 하고자 하는 목적의 표준안
-      OASIS/CEFACT 주도하여 기업의 규모나 지역적 위치에 관련 없이 인터넷을 통해 거래할  있도록 하는 규약들의모음
 
ebXML 필요성
-      전자상거래를 위한 단일 표준이 없음
-      XML 실제 전자 상거래의 표준적인 기반으로 인식하고 사용되고 있으나 구체적인 전자 상거래에서의 표준규약은 마련되어 있지 않음
 
ebXML 구성요소
1.     BP(Business Process)
-       다른 기업이 비즈니스 서비스 제공자의 비즈니스를 이용할  있도록 명세화 .
-       업무 프로세스업무절차를 정의한 부분임
-       기업간 거래에 있어서 공유하는 역할(Role), 관계(Relationship), 의무사항(Responsible) 등을 어떻게 수행(처리) 것인가를 상세히 정의하는 
-       비즈니스 프로세스와 이와 연관된 정보 모델 등의 일관된 모델링 방법 제공
-       업무 프로세스를 정의하는 과정에서 문서의 검토가 자연스럽게 이루어지므로 기존 문서 수준의 표준화에서 업무수준의 표준화로 확대가 가능한 것이 EDI 다름.
2.     CC(Core Components)
-       비즈니스 서비스에 사용되는 기능객체를 의미하며 이를 추출하여 이용할  있는 명세를 제공함
-        세계 개념과 비즈니스 개념과의 관계를 구문 독립적이고 명확하게 공통의 핵심 컴포넌트로서 구분하고 새로운확장이 가능하도록 정의한 객체
-       비즈니스 프로세스를 기반으로 재사용성확장성상속성을 지닌 의미 중립적인 비즈니스 객체
3.     RR(Registry/Repository)
-       Registry : 서비스의 메타데이터등 색인정보를 보관
-       Repository : 거래 상대자가 제출한 정보를 안전하게 보관
-       ebXML 구현 인프라의 핵심요소
4.     TP(Trading Partner)
-       거래상대자의 프로파일(TPP) 작성  거래협약(TPA) 작성
-       ebXML 핵심 컨텐츠 부분임
-       CPP(Collaboration Protocol Profile)
-       CPA(Collaboration Protocol Agreement)
5.     MS(Message Service)
-       각각의 요소 사이에 메시지 전송  보안성을 규정
-       ebXML 거래 당사자들간의 비즈니스 메시지들을 교환하기 위한 표준 방법을 제공
 
ebXML 운영 시나리오

 
 
 
 
     기업A ebXML등록기를 인지하고 있으며, ebXML 준수하는 거래를 하기 위하여 등록기에 ebXML규격서를 요청한다.
     등록기는 ebXML BP 규격서를 기업A에게 제공한다.
     기업A 규격서를 받아서 검토한  규격서에 따라서 자신의 시스템을 구축한다.
     기업A 자신의 구현내역참조링크거래 파트너 프로필 (TPP: Trading Partner Profile) 등을 등록기에 제출한다.
     TPP  기업의 ebXML능력과 제약시나리오 등의 내용을 포함한다등록기는 업무 객체의 형식과 사용이 정확함을검증한  기업A에게 승인되었음을 전달한다.
     기업A 중소규모의 기업B에게 ebXML 사용하여 거래를 하고자 함을 통지하면기업B 자신의 기존 응용어플리케이션과 접속이 가능하고 ebXML 준수하는 응용어프리케이션을 획득하여 설치하게 된다 ebXML응용은 기본적인객체 라이브러리와  기업이 속한 산업분야의 BP 모델 등을 포함하고 있으나새로 등록된 기업A 관한 정보는 없으므로이를 입수하기 위하여 등록기에 기업A 관한 질의를 하게 된다.
     기업B 등록기로부터 기업A 관한 프로필을 획득한다.
     TPP(Trading Partner Profile) 바탕으로 기업 A 지원하는 특정 시나리오를 수행할  있는지를 결정하게 된다시나리오를 실행하기 전에기업B 작성된 거래 파트너 합의 (TPA: Trading Partner Agreement)  작성하여 기업A 응용 인터페이스에 제출한다.
     메시지 처리사고 처리보안 등의 요구사항과 시나리오를 규정하고 있는 TPA 수신한 기업A  TPA 승인되었음을 기업B ebXML응용어플리케이션에 통보하게 된다.
     기업A 시나리오가 아직 기업B 응용에 존재하지 않기 때문에 등록기에 요청하여  시나리오를 확보한다.
     기업A 기업B ebXML규격서를 사용하여 B2B거래를 실행하게 된다.
 
ebXML Web Service 비교
구분
ebXML
Web Service
서비스 정보
-      RR
-      (B2B) Business Collaboration
-      Registry Federation(v3.0)
-      UDDI
-      (A2A) Application Integration
-      Registry Federation 기능 없음
-      각각의UDDI 연경된 기능은 정의 것이 없음
서비스 흐름
-      BP
-      기업간 거래의 역할관계의무사항 등을 정의한 시나리오
-      BP
-      다수  서비스를 연결한 복합  서비스를 제공하기 위한 시나리오
서비스의 구체적구현
-      XML 사용한 것으로만 정의
-      BPML4WS
 
ebXML 기타 저자 상거래 안과의 비교
구분
ebXML
eCo
UDDI
RosettaNet
Biztalk
대상산업
특별한 규정 없음
특별한 규정 없음
특별한 규정 없음
IT & 전자 부품
특별한 규정 없음
통신프로토콜
HTTP, SMTP
HTTP
HTTP(SOAP)
HTTP/CGI
HTTP(SOAP)/MSMQ
서비스찾기
지원
확장 지원
지원
없음
지원
레파지토리
분산형태
로컬에 위치
분산형태
없음
지원
메시지 형식
XML Document(MIME)
XML Document
XML Document
XML Document(MIME)
Biztalk Document기반을  Biztag
보안
S/MINE, 디지털 서명
선택적임
각각 UDDIregistry에서 인증
HTTP SSL/디지털 서명  인증서
표준화된 계층정보
온톨로지
Common Business Object
Common Business Library
NAICS, UN/SPSC
Technical and Business Dictionaries
Collection of Biztag
 
ebXML 파급효과
-      IT 산업 측면으로 보면 주요 IT기업의 ebXML 지원 제품 출시  시장 지배력 강화 노력 증대 기여
-      새로운 신생기업에게 새로운 기회를 주는 시장
-      경제적 측면으로 전자상거래 활성화에 따른 경제의 역동성 증가
-      신생기업에게 진입 장벽을 낮추어   있는 새로운 전자 상거래 관행 장착
 
ebXML 향후 전망
-      현재 EDI 채택하고 있는 대기업들이 병행적으로 ebXLM 사용을 시작으로 장기적으로는 대부분 기업이 ebXML 사용하여 전자 상거래를  것으로 예견됨
-      그러므로 기업은 ebXML 대한 표준화 동향을 예의 주시하여 신규시장 진입  새로운 기술에 대비하여야 
-      ebXML 이용한 B2B전자 상거래는 새롭게 시작하는 중소기업에게 신규시장에서의 새로운 도약기회를   있으므로이에 대한 대비 필요

[출처] ebXML |작성자 피비티

'BIZTALK > DEFINITION' 카테고리의 다른 글

Microsoft는 BizTalk Server를 이해  (0) 2009.12.22
SOA와 미들웨어, EAI하고 차이  (0) 2009.12.22
SOA와 EAI  (0) 2009.12.22
EAI 연동방안의 차이점  (0) 2009.12.22
EAI와 ERP의 차이점  (0) 2009.12.22