'분류 전체보기'에 해당되는 글 317건

  1. 2012.01.24 제네릭 - 클래스, 메소드 제네릭, 제약조건 where
  2. 2012.01.22 자주쓰이는 Win32 API 함수들
  3. 2012.01.22 global 컨텍스트 키워드 와 :: 연산자
  4. 2012.01.22 C# 네트웍 프로그래밍 관련 코딩 팁
  5. 2012.01.21 IEnumerable, IEnumerator
  6. 2012.01.21 스레드 일시정지, 재시작 구현(ManualResetEvent 이용)
  7. 2012.01.21 C# _ 멀티스레드,ManualResetEvent,동기화 를 시켜보자
  8. 2012.01.21 스레드 동기화를 위한 AutoResetEvent와 ManualResetEvent
  9. 2012.01.21 _문자열 마샬링
  10. 2012.01.21 _플랫폼 호출 데이터 형식
  11. 2012.01.21 _DllImport 어트리뷰트와 StructLayout 어트리뷰트
  12. 2012.01.21 16진수 문자열 변환
  13. 2012.01.21 VB.NET and C# 의 비교문서
  14. 2012.01.21 C# 으로 만든 DLL asp에서 사용
  15. 2012.01.21 C# 프로그램 중복 실행 방지 Mutex / C# Using a mutex to prevent multiple application from running 1
  16. 2012.01.21 .Net single-instance application without activation
  17. 2012.01.21 C# 사운드 재생 1
  18. 2012.01.21 ebXML
  19. 2012.01.19 SELECT 함수
  20. 2012.01.19 멀티플렉싱(multiplexing)과 select()함수
  21. 2012.01.19 C# 멀티코어 프로그래밍
  22. 2012.01.19 [C#] Template Method 패턴
  23. 2012.01.19 [C#] Singleton 패턴이 적용된 File 로거
  24. 2012.01.19 [C#] 리플렉션 Reflection 1
  25. 2012.01.18 [C#] 소멸자 (de-constructor, finalizer)
  26. 2012.01.18 WPF Datagrid
  27. 2012.01.18 MS Project 뷰어
  28. 2012.01.18 링크
  29. 2012.01.18 Thread vs ThreadPool
  30. 2012.01.18 마샬링 (Marshaling)
posted by 방랑군 2012. 1. 24. 23:33

List<T>는 ArrayList의 Generic 버전이다.
Dictionary<K, V>는 HashTable의 Generic 버전이다. 등등.

 

특정 Application에서 Collection을 운용하는 경우, 관리되는 데이터 타입은 결정되어있을 것이다.
이러한 경우 ArrayList나 HashTable을 사용하는 것보다 Generic 버전의 Collection을 사용하는 것이 옳다.

 

Generic Collection 개체는 불필요한 Boxing/Unboxing 연산을 수행하지 않기 때문에 더 빠르고, 컴파일 타임에 데이터 타입이 지정되기 때문에 잘못된 데이터의 삽입으로 발생할 수 있는 오류를 사전에 잡을 수 있는 장점이 있다.

 

Generic은 C++의 Template와 닮아있다.
따라서 C++에서처럼 Generic 형태의 클래스, 메서드 또한 선언할 수 있다.

 

1. Generic 클래스
ex)
class 클래스명<T> where T:new()
{
 T _instance;

 public T GetInstance()
 {

  if (_instance == null)

  {

    _instance = new T();

  }
  _instance = value;
 }
}

 

2. Generic 메서드
ex)
static void Swap<T>(ref T i, ref T j)
{
 T temp;
 temp = i;
 i = j;
 j = temp;
}

 

C++과 비교하여 추가된 점은 제약 조건을 줄 수 있다는 점이다.

 

선언된 형식 뒤에 기재할 수 있다.
where T:struct => 값 타입만 허용
where T:class => 참조 타입만 허용
where T:new() => Default 생성자가 있을 때만 허용
where T:base => base로부터 파생된 클래스만 허용

 

static void Swap<T>(ref T i, ref T j) where T:struct // 값 타입만 허용하는 Swap 메서드.

 

두가지 이상의 제약조건을 설정하는 경우.
class 클래스명<T, U> where T:제약형식1, 제약형식2 where U:제약형식

[출처] [C#] Generic|작성자 에스이오케이

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

출처 :  http://jok3.tistory.com/27 


역분석을 하다보면 api함수로 찾아줄때가 많은데 자주쓰이는 함수들을 정리해 봤습니다.
첨부파일은 원하는 함수를쓰면 그함수의 쓰임세가 설명되있는 도움말파일이라고 보시면 됩니다.





-파일 생성 & 열때.
16-bit : CreateFile
32-bit : CreateFileA
wide : CreateFileW


-파일 입출력(Read&Write)
ReadFile : 읽기
WriteFile : 쓰기

-파일 접근(Access)
SetFilePointer : 포인터 조정

-시스템 디렉토리 얻어오는 함수
16-bit : GetSystemDirectory
32-bit : GetSystemDirectoryA
wide : GetSystemDirectoryW


-.ini 구성설정에 관련된 함수들
16-bit : GetPrivateProfileString
GetPrivateProfileInt
WritePrivateProfileString
WritePrivateProfileInt
32-bit : GetPrivateProfileStringA
GetPrivateProfileIntA
WritePrivateProfileStringA
WritePrivateProfileIntA
wide : GetPrivateProfileStringW
GetPrivateProfileIntW
WritePrivateProfileStringW
WritePrivateProfileIntW

-레지스트리의 키를 생성 혹은 삭제할때
16-bit : RegCreateKey
RegDeleteKey
32-bit : RegCreateKeyA
RegDeleteKeyA
wide : RegCreateKeyW
RegDeleteKeyW

-현재 열려진 레지스트리 키를 읽을때
16-bit : RegQueryValue
32-bit : RegQueryValueA
wide : RegQueryValueW

-레지스트리 키를 열때
16-bit : RegCloseKey
RegOpenKey
32-bit : RegCloseKeyA
RegOpenKeyA
wide : RegCloseKeyW
RegOpenKeyW

-객체에서 문자열을 읽을때
16-bit : GetWindowText
GetDlgItemText
32-bit : GetWindowTextA
GetDlgItemTextA

wide : GetWindowTextW
GetDlgItemTextW

-정수여부 상관
GetDlgItemInt

-객체의 텍스트를 지정
16-bit : SetWindowText
SetDlgItemText
32-bit : SetWindowTextA
SetDlgItemTextA
wide : SetWindowTextW
SetDlgItemTextW


-메시지 박스
16bit : MessageBox
MessageBeep
32bit : MessageBoxA
MessageBoxExA
wide : MessageBoxW
MessageBoxExW

-메시지 관련
16bit : SendMessage
WSPRINTF
32bit :SendMessageA
wide : SendMessageW

-날짜와 시간을 구할때
GetSystemTime
GetLocalTime
SystemTimeToFileTime


-창을 생성 & 제거할때
16bit : CreateWindow
CreateWindowEx
DialogBoxParam
DestroyWindow
EndDialog
showwindow
bitblt
32bit : CreateWindowA
CreateWindowExA
DialogBoxParamA
wide : CreateWindowW
CreateWindowExW
DialogBoxParamW


-CD롬을 요구하는 함수 들
16bit : GetDriveType (만약 eax=5 라면 CD롬 체크 이다.)
GetLogicalDrives
GetLogicalDriveStrings
32bit : GetDriveTypeA
GetLogicalDrivesA
GetLogicalDriveStringsA
wide : GetDriveTypeW

-리턴 코드:
값 설명
0 Drive Cannot Be determined
1 Root Dir Does not exist
2 DriveRemoveable
3 A Fixed Disk (HardDrive)
4 Remote Drive(Network)
5 Cd-Rom Drive <==============
6 RamDisk

GetLogicalDrivesW
GetLogicalDriveStringsW

-Win NumberSerial:
GETWINDOWWORD
GETWINDOWLONG

+ORC가 제안한 훌륭한 함수
BOZOSLIVEHERE
HMEMCPY
GLOBALGETATOMNAME
posted by 방랑군 2012. 1. 22. 20:13
출처 :   http://blog.naver.com/alfustnals?Redirect=Log&logNo=140140341010 

 global 컨텍스트 키워드 :: 연산자

 global 컨텍스트 키워드 :: 연산자

 1] 모든 C# 프로그램의 기본 네임스페이스

 2] 다른 경우 ==> 명명되지 않는 전역 네임스페이스를 가리킵니다

 3] 네임스페이스 별칭 한정자는 global 일 수 있다. 

   ==> 전역 네임스페이스에서 조회가 실행

:: ==> 네임스페이스 별칭 한정자

 식별자를 조회하는 데 사용

 ==> 두개의 식별자 사이에 온다.

사용이유

MSDN : http://msdn.microsoft.com/ 

System이라는 자체 네임스페이스는 만들지 않는 것이 좋으며, 이러한 네임스페이스를 만드는 코드는 거의 찾아볼 수 없습니다. 그러나 보다 큰 프로젝트에서는 여러 가지 형태의 네임스페이스 중복이 발생할 수 있습니다. 이러한 경우 전역 네임스페이스 한정자를 사용하면 확실하게 루트 네임스페이스를 지정할 수 있습니다.

예제

      MSDN 참조 : http://msdn.microsoft.com/ko-kr/library/c3ay4x3d(VS.90).aspx

------------------------------------------------------------------------------- 

using colAlias = System.Collections;
namespace System
{
    class TestClass
    {
        static void Main()
        {
            colAlias::Hashtable test = new colAlias::Hashtable();
            

            test.Add("A""1");
            test.Add("B""2");
            test.Add("C""3");


            foreach (string name in test.Keys)
            {
              global::System.Console.WriteLine(name + " " + test[name]);
            }
        }
    }
}

  
posted by 방랑군 2012. 1. 22. 00:14

1. byte[] 배열 합치기

C의 유연함에 익숙한 사용자는 갑갑할 수 밖에 없다. System.Array의 인스턴스는 특정 위치부터 배열을 복사하는 기능을 제공하지 않는데, 인터넷을 뒤져보니 그냥 for 루프로 돌리는 사람도 있고, CopyTo() 메서드를 잘못 이해해서 틀린 정보를 제공하는 사람도 있고 가지가지다.

 

<Array.CopyTo() 메서드의 틀린 사용 예>

byte[] a= new byte[3]{1,2,3};

byte[] b= new byte[4]{4,5,6,7};

byte[] c= byte[a.Length+b.Length];

a.CopyTo(c,0);

b.CopyTo(c,a.Length); 

 

 얼핏 보면 올바른 코드로 보이지만, CopyTo의 두 번째 인자는 목적 배열의 인덱스가 아니라 소스 배열의 인덱스라는데 이 코드의 치명적인 오류가 있다.

 즉, 위의 코드에의 결과는 c={7,2,3} 이 되어 버린다.

 

결론은 Array.Copy() 메서드를 사용한다.

 

위 코드는 아래처럼 바꾸면 된다.

Array.Copy(a, 0, c, 0, a.Length);

Array.Copy(b, 0, c, a.Length,b.Length);

 

2. htonl, ltons 소켓라이브러리 함수와 같은 기능을 하는 .NET 라이브러리는?

System.Net.IPAddress.HostToNetworkOrder()

System.Net.IPAddress.NetworkToHostOrder()

 

3. int, short 같은 정수를 byte[]으로 상호 변환하려면?

System.BitConverter의 메서드를 사용한다.

 

System.BitConverter.ToInt32(packet, 0);

 

4. 비동기 메서드 BeginXXX(), EndXXX()를 사용할 때 윈폼 컨트롤에 접근하는 코드는?

 비동기 메서드 BeginReceive, EndReceive 등을 사용할 때 EndReceive 에서는 AsyncCallback 개체를 사용하여 별도의 스레드에서 데이터를 수신하게 되는데, 이 스레드에서는 윈폼 컨트롤로 바로 출력할 수 없다. 이 때는 윈폼의 Invoke 메서드를 사용한다.

 

 Invoke의 첫 번째 인자는 Delegate이고 두 번째 인자는 관련된 변수이다. 아래는  EndReceive에서 byte[]형 데이터를 수신해서 ReceivedData 라는 사용자 이벤트를 발생했을 경우의 예이다.

        delegate void VerbosePrinter(string msg);

        void PrintText(string s)
        {
            txtOut.AppendText(s + "\r\n");
            txtOut.ScrollToCaret();
        }
        void p(string s)
        {
            this.Invoke(new VerbosePrinter(PrintText), s);
        }

        void cli_ReceivedData(object sender, byte[] bytes)
        {

               p(Encoding.Default.GetString(bytes);
        }

 

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
posted by 방랑군 2012. 1. 19. 22:05

파일 디스크립터의 변화를 확인하는 함수
기본적으로 blocking 함수(확인할 파일 디스크립터에 변화가 생길 때까지 무한 대기)

멀티플렉싱 서버를 구현하기 위한 방법으로 select 함수가 가장 많이 사용되는 방법이고 윈도우즈 시스템에서도 동일한 이름으로 동일한 기능을 하는 함수를 제공하고 있으니 이식성에서도 높은 점수를 줄 수 있다

select 함수를 사용하게 되면, 한 곳에 모아놓은 여러 개의 파일 디스크립터를 동시에 관찰할 수 있다.
수신할 데이터를 지니고 있는 파일 디스크립터가 어떤 것들인지, 데이터를 전송할 경우 블로킹되지 않고 바로 전달 가능한 파일디스크립터는 어떤 것들인지, 그리고 예외가 발생한 파일 디스크립터는 어떤 것들인지 정도가 관찰 내용이 된다.

select 함수의 기능과 호출 순서

-- select 함수 사용 순서 --
1. 디스크립터 설정
2. 검사 범위 설정
3. 타임 아웃 설정
4. select 함수 호출
5. 결과 확인
-------------------------



===== 디스크립터 설정 =====

1) 파일 디스크립터 설정
  - 변화를 확인할 파일 디스크립터들을 한 묶음으로 모아둔다.
  - 파일 디스크립터를 모아두는 비트단위 자료형 fd_set 이용
  - 3가지 변화(수신 데이터 존재유무, 데이터 송신 가능여부, 소켓의 예외상황 발생여부)별로 파일 디스크립터들을 구분지어 모아둠



fd_set 자료형 관련 함수
 FD_ZERO(fd_set * fdset); //fd_set 초기화 함수
 FD_SET(int fd, fd_set * fdset); //해당 파일디스크립터 fd를 1로 셋
 FD_CLR(int fd, fd_set * fdset); //해당 파일디스크립터 fd를 0으로 셋
 FD_ISSET(int fd, fd_set * fdset); //해당 파일디스크립터 fd가 1인지 확인


===== 검사범위 설정 =====

2) 검사할 파일 디스크립터의 범위 지정
  - 검사해야할 파일 디스크립터의 개수를 전달.
  - 가장 큰 파일 디스크립터 값에 1을 더함(파일 디스크립터 값이 0부터 시작하므로)


===== 타임아웃 설정 =====

3) 타임 아웃 설정
  - select 함수가 blocking되는 것을 피하기 위해 타임 아웃을 설정함. 

===== select 함수의 원형 ===== 

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int select(int n, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout);

   리 턴 값    의    미
   -1    오류 발생
    0    타임 아웃
    0보다 큰 수    변화발생 파일 디스크립터 수

- n : 검새 대상이 되는 파일 디스크립터의 수

- readfds : 이 리스트에 있는 식별자들은 시스템에 의해 즉시 입력이 가능한지 확인된다. 즉, 입력 가능으로 인해 반환된 식별자에 대해 recv()는 블로킹되지 않는다.

- writefds : 이 리스트에 있는 식별자들은 시스템에 의해 즉시 출력이 가능한지 확인된다, 즉 출력 가능으로 인해 반환된 식별자에 대해 send()는 블로킹되지 않는다.

- excepfds : 이 리스트에 있는 식별자들은 시스템에 의해 예상되는 예외 사항이나 에러가 발생했는지 확인된다. TCP소켓에서 발생할 수 있는 이러한 예상되는 예외 사항의 한 예로 상대방이 데이터 전송 중에 TCP연결을 끊었을 때가 있다. 이런 경우, 다음에 이어지는 읽기 또는 쓰기는 실패하고 ECONNRESET에러를 나타낸다.

- timeout : 함수 호출 후, 무한 대기 상태에 빠지지 않도록 타임-아웃(time-out)을 설정하기 위해
 인자를 전달한다.

※ select 함수 호출시 전달되는 파일 디스크립터의 정보를 소켓뿐 아니라 파일을 나타내는 경우에도
   전달 가능한다.


===== 결과 확인 =====


fd_set자료형에 파일디스크립터 0(stdin), 3의 변화를 확인하기 위해 설정




Select() 호출하면 변화가 생긴 파일디스크립터는 1로 세팅됨(그림에서 파일디스크립터 3이 변화가 발생한 것을 확인할 수 있음)

- 변화가 확인된 해당 파일디스크립터와 데이터 통신을 진행하면 된다.


[ 파일 디스크립터 범위 설정하기 ]

select 함수는 여러 파일 디스크립터를 검사하고, 그 결과를 전달해 준다. 
select 함수는 여러 개의 파일 디스크립터를 확인해야 하는데, 이왕이면 확인해야 하는 파일 디스크립터의 범위를 제한해 주면, 보다 효율적으로 수행할 수 있다.
그래서 select 함수의 첫 번째 인자로 검사해야 하는 총 디스크립터의 개수를 넘겨주게 된다.
그러나 일반적으로 디스크립터는 생성될 때마다 값이 1씩 증가하기 때문에 가장 큰 파일 디스크립터 값에 1을 더해서 인자로 전달하면 된다.
1을 더하는 이유는 디스크립터 값이 0부터 시작하기 때문이다. 따라서 인자로 n이라는 값을 넘겨주게 되면 select 함수는 검사하게 되는 파일 디스크립터의 범위를 부터 n-1로 설정된다.
따라서 반드시 1을 더해줘야 한다.


[ 타임아웃 (time out) 설정하기 ]

타임아웃을 설정하기 위한 timeval 구조체

struct timeval
{
    long tv_sec; /* seconds */
    long tv_usec; /* microseconds */
}
예를 들어서 tv_sec가 3이고 tv_usec가 500000 이면 타임아웃은 3.5초로 설정된다. 
이렇게 설정한 timeval 구조체 변수의 포인터를 select 함수의 마지막 인자(timeout 인자)로 넘겨주게 되면 파일 디스크립터에 아무런 변화가 없더라도 3.5초가 지나면 무좋건 리턴하게 된다. 만약에 타임 아웃을 설정해 주지 않을 경우, NULL 포인터를 인자로 전달하면 된다.


[ select 함수 호출 이후 결과 확인 ]
select 함수가 리턴되고 나서 무엇보다도 중요한 것은 결과를 얻는 것이다. 일단 함수 호출이 정상적으로 리턴했다는 것은 파일 디스크립터에 변화가 있엇거나, 아니면 타임아웃이 발생했거나 둘 중에 하나이다. 

리턴 값이 -1인 경우는 오류발생을 의미한다. 또한 0이 리턴 된 경우에는 타임아웃에 의해 리턴되었음을 의미한다. 즉 0이 리턴된 경우 파일 디스크립터에 아무런 변화도 발생하지 않았다는 의미가 된다. 
그러나 리턴된 값이 0보다 큰 경우에는, 변화가 발생한 파일 디스크립터의 수를 의미하게 된다.
예를 들어 수신할 데이터가 존재하는 파일 디스크립터가 두 개 발생했다면, 2가 리턴될 것이다.

-------- select 호출 전 / 후 --------

==select 호출 전 ==
fd0  fd1  fd2  fd3  fd4
| 1 | 0 | 0 | 1 | 0 | 0 |...........................

==select 호출 후==
fd0  fd1  fd2  fd3  fd4
| 0 | 0 | 0 | 1 | 0 | 0 |...........................

select 함수의 예)

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

#define BUFSIZE 30

int main(int argc, char *argv[])
{
  fd_set reads, temps;
  int result;

  char message[BUFSIZE];
  int str_len;
  struct timeval timeout;

  FD_ZERO(&reads);  //0으로 초기화
  FD_SET(0&reads);  //파일디스크립터 0(stdin) 설정

  
/*timeout.tv_sec = 5;
   * timeout.tv_usec = 100000;*/

          //잘못된 timeout 설정
          
  while(1)
  {
    temps = reads;  //원본 보존 위해 복사본 temp를 이용

    timeout.tv_sec = 5;  //timeout 설정
    timeout.tv_usec = 0;

    result = select(1&temps, 00&timeout);
    if(result == -1)
    {
      puts("select(): 오류 발생");
      exit(1);
    }

    else if(result == 0)  //timeout에 의한 return
    {
      puts("select(): 시간이 초과되었습니다.");
    }

    else
    {
      if(FD_ISSET(0&temps));
      {
          str_len = read(0, message, BUFSIZE);
          message[str_len] = 0;
          fputs(message, stdout);
      }
    }
  }
  
  return 0;
}



[결과]



이미 주비해둔 fd_set 변수를 임시 변수에 복사해 두고 있다. 여기에는 그럴만한 이유가 있다. select 함수 호출이 끝나면 변화가 생긴 파일디스크립터 위치를 제외한 나머지 위치의 비트들이 0으로 초기화된다. 따라서 원본 변수를 직접 select 함수의 인자로 전달해 버리면 또 다시 변수를 설정하는 과정을 거쳐야 한다.
이를 막기 위해서 원본은 보존 하고 임시 변수에 원본을 복사해서 이것을 가지고 select 함수를 호출한다. 일반적인 select 함수 사용이니 반드시 기억해야한다.
그리고 timeout 변수가 반복문 내부에 존재하게 되는데... select 함수를 호출하기 전에 매번 타임 아웃을 재 설정 하게 되어 있는 것이다. 다시 비효율적인 방법으로 생각할수도있으나 select 함수 호출이 끝나게 되면 타임아웃이 발생하기 까지 남아 있던 시간이 timeval 구조체 변수에 저장된다.
따라서 timeval 구조체 변수를 한번만 설정하고 계속해서 select 함수를 호출한다면 나중에는 0이 된다.
select 함수를 호출하고 만약 콘솔로부터 입력된 데이터가 있다면 0보다 큰 수가 리턴될 것이며, 입력이 없어서 타임아웃이 발생하는 경우에는 0이 리턴될것이다.

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

.Net single-instance application without activation  (0) 2012.01.21
C# 사운드 재생  (1) 2012.01.21
멀티플렉싱(multiplexing)과 select()함수  (0) 2012.01.19
C# 멀티코어 프로그래밍  (0) 2012.01.19
[C#] Template Method 패턴  (0) 2012.01.19
posted by 방랑군 2012. 1. 19. 21:51

멀티플렉싱(multiplexing)>>> 통신분야에서는 (다중화기)

지금까지 작성했던 프로그램들은 모두 하나의 단일 채널에서 일어는 입/출력만을 다루었습니다 즉 이전의 모든 버전의 에코 서버는 한번에 하나의 클라이언트 연결만을 처리 하였습니다 하지만 응용프로그램은 여러 채널의 입/출력을 동시에 처리하는 능력을 요구할 때가 자주 있습니다예를 들어 동시에 여러 포트를 열어서 에코서버를 할때 서버가 각 소켓을 생성하고 이를 각 포트에 바인딩 한 후 무슨 일이 일어날까를 생각해 봅시다기존방식에는 문제점이 발견되는데 서버는 연결을 accept할 준비가 되어있습니다 하지만 어떤 소켓을 선택해야 할지 선택을 하지 못합니다아무 서버나 연결하게 된다면 기존의 대기하고 있는 소켓역시 대기가 되어버리는 불편한 상황이 발생합니다물론 이러한 문제는 non-bloaking소켓을 이용하여 해결이 가능하지만 그것보다는 특정 소켓의 입/출력이 준비가 될때까지 서버를 bloacking을 하는 것이 좋습니다

 

하지만 단점도 있습니다 정리하자면

프로세스 생성에 많은 양의 연산메모리 공간 요구. IPC (inner process communcation) 방법도 복잡합니다

 


이런한 일련의 과정들은 가능하게 하는 것이
 linux상에서 다시 말하면 unix상에서 제공해주는 select를 사용하면 됩니다 select는 입/출력이 예상되는 소켓의 식별자를 리스트로 명시하고 리스트의 식별자중 준비되어진 식별자를 준비가 되었는지를 반환하여 알리고 blocking이 되지 않을 것이라는 것을 확신하고 진행하게 됩니다

 

 

전반적인 순서는 아래와 같습니다

하나의 서버에 여러개의 클라이언트 제어
서비스 품질은 멀티프로세스보다 더 떨어지는것 같아보입니다
실질적으로 서버와 클라이언트의 통신에서 데이타 송수신은 매우 작다 
그렇기 때문에 많은 클라이언트에게 서비스 할 수 있습니다.

하나의 프로세스가 해당 클라이언트n개 즉...파일 디스크립터를 묶어서
관리를 합니다
   
※ 즉 fd_set으로 묶어서 파일 디스크립터정보를 담습니다

 





select()함수>>>
select 
함수를 사용하기 위해서 간단한 순서를 확인해보자

참고>>그림


----- select 함수 사용 순서 -------

1. 디스크립터 설정

2. 검사 범위 설정

3. 타임 아웃 설정

4. select 함수 호출

5. 결과 확인

------------------------------

 

 
 

1. 디스크립터 설정


1)
파일 디스크립트 설정

 

fd_set 수형;

0

1

0

1

.........

fd0  fd1  fd2  fd3

 

fd0 : stdin    fd1 : stdout    fd2 : stderr    fd3 : socket

 

변화를 확인할 파일 디스크립터들을 한 묶음으로 모아둔다

 

fd_set 자료형 관련함수

  FD_ZERO(fd_set * fdset);        //fd_set 초기화 함수

  FD_SET(int fd, fd_set * fdset);   //해당 파일디스크립터  fd  1로 셋

  FD_CLR(int fd, fd_set * fdset);   //해당 파일디스크립터  fd  0으로 셋

  FD_ISSET(int fd, fd_set * fdset);  //해당 파일디스크립터  fd  1인지 확인

 

사용방법 예제


2)
검사할 파일 디스크립터의 범위 지정

 검사해야할 파일 디스크립터의 개수를 전달

 가장 큰 파일 디스크립터 값에 1을 더함(파일 디스크립터 값이 0부터 시작하므로)

 

3)타임 아웃 설정

 - select함수가 blocking 되는 것을 피하기 위해 타임 아웃을 설정함

 

2. select함수 호출

 
헤더파일

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>


원형

int select(int n fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

                                                                                                  리턴값 : 성공시 0  이상... 오류 발생시 -1 리턴
                                                                                 0을 리턴하는 경우에는 타임아웃에 의해 리턴되었음을 의미
                                                                                 보다 큰경우는 변경된 파일 디스크립터의 수를 의미한다. 

인자 값 분석>>


n : 
검색 대상이 되는 파일 디스크립터의 수

 

readfds : "입력스트림에 변화가 발생했는지확인하고자 하는 소켓들의 정보를 전달합니다여기서 입력 스트림에 변화가 발생했다는 것은 수신할 데이터가 있다는 뜻

 

writefds : "데이터 전송 시블로킹되지 않고 바로 전송이 가능한지확인하고자 하는 소켓들의 정보를 전달
 

excepfds : "예외가 발생했는지확인하고자 하는 소켓들의 정보를 전달
 

timeout : 함수 호출 후무한 대기 상태에 빠지지 않도록 타임-아웃(time-out)을 설정하기 위해 인자를 전달

 

예제>>

select(1,&reads,0,0,5)

<감지>5초동안 감지 수신에 변화가 없는지 감지하고 나와라 리턴값 = 1-

검사 디스크립트 수는 1


위 예제의 select같이 동작하는 프로그램을 작성합니다
 

select.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

#define BUFSIZE 30

int main(int argc, char *argv[])
{
  fd_set reads, temps;
  int result;

  char message[BUFSIZE];
  int str_len;
  struct timeval timeout;

  FD_ZERO(&reads); //0
으로 초기화
  FD_SET(0,&reads); //
파일 디스크립터 0(stdin) 설정

  /*
  timeout.tv_sec 
= 5;
  timeout.tv_usec 
= 100000;
  */
  //
잘못된 timeout 설정(구조체 내에서만 업데이트된다)
  
  while(1)
  {
    temps = reads;
    
    timeout.tv_sec = 5//
실행후 다시 재설정해야한다
    timeout.tv_usec = 0;
    
    result = select(1&temps, 00&timeout);
    if(result == -1)
    {
      puts("select(): 
오류발생");
      exit(1);
    }
    else if(result == 0)
    {
      puts("select():
시간이 초과 되었습니다. ");
    }
    else
    {
      if(FD_ISSET(0,&temps))
      {
        str_len = read(0, message, BUFSIZE);
        message[str_len] = 0;
        fputs(message, stdout);
      }
    }
  }
  return 0;
}

 

결과>> 5초간 입력이 없을 경우 시간이 초과되었다는 경고 메시지가 출력됩니다

 

분석해보기>>
 
1)FD_ZERO(&reads); //0으로 초기화
    FD_SET(0,&reads); //
파일 디스크립터 0(stdin) 설정

1

0

0

0

.........

 

마지막 파일 디스크립터에 +1되게 되어있다?

 

1

0

0

1

.........

 

result = select(1&temps, 00&timeout);

수신데이터가 있는지 확인합니다 <5초설정>

확인할 파일디스크립트는 1개입니다

입력이 되었다면 result = 1



2)else
 if(result == 0) 5
초간 아무 변화가 없을때

 

0

0

0

0

.........


3)temps 
= reads; 
원본값으로 초기화 시켜주질 않을 경우

 while문을 한바퀴 돌고나면

1

0

0

0

.........

에서

0

0

0

0

.........

으로 변화되고 이후로는 계속 0인 상태가 됩니다

 

select사용시에는 원본을 저장 할 수 있는 변수를 써야 합니다


3. 결과 확인


참고>>
select()함수의 인자를 보면 이 중 n은 검사가 필요없는 가장 작은 식별자값으로써 최대 식별자  값보다 1이 작다 위에서 보면 소켓셋에 담을 수 있는 소켓 디스크립터의 최대갯수는 시스템 정의 상수인 FD_SETSIZE로 정의 되어 있지만 그 수가 상당히 크므로 매번 그 크기만큼 검사하면 비효율적이므로 이를 효율적으로 검사하기 위해서 정수 n을 전달하여 그 크기+1까지만 검사한다

 그 다음에는 각 소켓셋(읽기셋, 쓰기셋, 예외셋)이 파라미터로 들어가며 만약 NULL이 들어가면 그 소켓셋은 대상 리스트에 대한 입/출력 감시를 하지 않는다
 마지막 파라미터인 timeout은 NULL로 설정하면 읽기셋, 쓰기셋, 예외셋에 삽입한 소켓 중에 변화가 생길 때까지 대기하고 있다가 변화가 발생한 소켓의 수를 리턴하게 된다. 

timeout을 양수로 설정한 경우에는 변화가 발생한 소켓이 생길 때까지 대기하고 있다가 설정한 시간이 되면 변화가 발생한 소켓이 없더라도 대기상태를 해제하게 된다.


 이때 변화가 발생한 소켓이 없다면 0을 리턴하게 된다. 그리고 timeout 값이 0으로 설정되면 대기시간 없이 바로 리턴하게 된다

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

C# 사운드 재생  (1) 2012.01.21
SELECT 함수  (0) 2012.01.19
C# 멀티코어 프로그래밍  (0) 2012.01.19
[C#] Template Method 패턴  (0) 2012.01.19
[C#] Singleton 패턴이 적용된 File 로거  (0) 2012.01.19
posted by 방랑군 2012. 1. 19. 02:30

요즘 대부분의 컴퓨터가 멀티코어다 보니 가끔 노는 코어들을 보게 된다. 그래서 궁금증에 멀티코어 프로그래밍 기법이 있어 퍼와봤다.

일단 기본적인 코드는 데브피아에서 가져왔는데 실제 어떻게 돌아가는지 내부 설명이 없어서 좀 조사해 봤다.

일단 코드...


======================================================================================================================

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

const int NumOfThread = 5;

Thread[] threads = new Thread[NumOfThread];

for (int i = 0; i < NumOfThread; i++)
{
threads[i] = new Thread(ThreadProc);
threads[i].Start(i);
}


Process currentProcess = Process.GetCurrentProcess();

foreach (ProcessThread processThread in currentProcess.Threads)
{
processThread.ProcessorAffinity = currentProcess.ProcessorAffinity;
}


for (int i = 0; i < NumOfThread; i++)
{
threads[i].Join();
}

}


public static void ThreadProc(object threadId)
{
//스레드 작업

}

}

}

======================================================================================================================


코드 자체는 굉장히 심플하다. 실제 프로그램 만들때도 이렇게 심플하다면 좋겠지만 무언가 다른 문제점이 발생할지 모르니 왜 저 코드가 멀티코어 프로그래밍이 되는것인지 스스로 어느정도 파악해 보았다. 간단히 말하자면


Process currentProcess = Process.GetCurrentProcess();

currentProcess는 현재 프로세서의 정보를 가져오게 되고


foreach (ProcessThread processThread in currentProcess.Threads)
{
processThread.ProcessorAffinity = currentProcess.ProcessorAffinity;
}


현재 프로세서의 스레드를 하나씩 가져와서 ProcessorAffinity 속성을 현재 프로세서의 속성으로 바꿔 주는 코드 이다.

여기까지는 다른데 다 나와있는 설명이자 코드 설명이고 간단하게 내가 파악해본 내부 구조는 일반적으로 쿼드코어 PC의 환경이라고 한다면 일반적으로 제작한 프로그램은 아래와 같은 구조를 가지게 된다.




해당 프로세서는 쿼드쿼어중 하나의 코어에서 실행되게된다. 이 속성이 바로 ProcessorAffinity 속성으로 해당 코어중 하나가 처리할수 있도록 되어 있다. 프로세서에서 생성한 스레드는 해당 프로세서에서 실행이 되기 때문에 다수의 코어가 작동을 하지 않는다.

그래서 하위의 스레드의 속성을 상위 프로세서와 동일하게 바꿈으로써 실제 코어가 스레드의 작업을 처리할 수 있도록 설정하는 것이다.

구지 그림으로 표현한다면....




이런식으로 설정을 변경하는 것이다. 내 개인적인 조사기때문에 실제 다를수 있다;;; 위코드야 워낙 심플하니 문제가 없겠지만 실제 복잡한멀티코어 프로그래밍에서 중요한것은 문법이 아닌 시스템 전체의 구조와 각부분간의 영향력이 아닌가 싶다. 만약 오류사항이나 수정사항이 있으면 알려주세요~

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

SELECT 함수  (0) 2012.01.19
멀티플렉싱(multiplexing)과 select()함수  (0) 2012.01.19
[C#] Template Method 패턴  (0) 2012.01.19
[C#] Singleton 패턴이 적용된 File 로거  (0) 2012.01.19
[C#] 리플렉션 Reflection  (1) 2012.01.19
posted by 방랑군 2012. 1. 19. 01:15

예제를 보면 이해가 빠릅니다.

Template Method 패턴은 상위 클래스에서 특정 동작의 Template만 정의해두고,

구체적인 단계의 동작 방법은 하위 클래스에서 재정의하는 패턴입니다.

 

동일한 동작의 흐름을 갖는 클래스 타입이 여럿 존재할 시 Template Method 패턴을 적용하면

전체 구성이 깔끔해지고 코드가 간결해지는 장점이 있습니다.

 

가상함수를 protected로 선언한 것과 상속받은 클래스에서 Machine 클래스를 어떻게 이용되고 있는지만

눈여겨 보시면 쉽게 이해가 가능합니다.

 

public class Machine
{
    
public void Execute()
    {
        Start();
        Produce();
        Stop();
    }

 

    protected virtual void Start()
    {
        
Trace.WriteLine("Machine.Starting..");
    }

 

    protected virtual void Produce()
    {
        
Trace.WriteLine("Machine.Producing..");
    }

 

    protected virtual void Stop()
    {
        
Trace.WriteLine("Machine.Stopping..");
    }
}


 

    public class PizzaMachine : Machine
    {
        
protected override void Produce()
        {
            
Trace.WriteLine("PizzaMachine.Producing..");
        }
    }


 

다음과 같이 호출하였을 때,


new PizzaMachine().Execute();

 

실제 호출 흐름은 아래와 같이 이루어집니다.

 

1. Machine.Execute() is invoked

2. Machine.Start() is invoked

3. PizzaMachine.Produce() is invoked

4. Machine.Stop() is invoked

 

도식화 하여보면 아래와 같습니다.

PizzaMachine 클래스의 역할이 가벼워진 것을 볼 수 있습니다.

동일한 흐름을 갖는 다양한 Machine들이 추가될 때 따르게 되는 이점은 결코 작지 않습니다.

 



posted by 방랑군 2012. 1. 19. 01:14

Singleton 패턴은 굳이 용어를 들먹이지 않아도 자연스레 사용되는 패턴 중 하나입니다.

하나의 클래스에 대하여 하나의 인스턴스만 생성되게끔 만들어주는 것인데요.

 

단순히 로그를 남기는 File 로거를 구현해보고자 합니다.

클래스 다이어그램을 보시면 이해가 빠릅니다.

 



클래스 내부에 static 인스턴스를 반환하는 메서드를 포함하고, 생성자를 private로 제한함으로써

해당 클래스의 인스턴스를 생성하는 방법을 제한할 수 있습니다.

즉, 해당 클래스의 인스턴스를 획득할 수 있는 방법은 static 인스턴스를 반환하는 메서드를 호출하는 방법 뿐이겠지요.

 

public class LogManager
{
    
private static LogManager _instance;

 

    public static LogManager Instance
    {
        
get 
        {
            
if (_instance == null)
                _instance = 
new LogManager();

            return _instance; 
        }
    }

 

    private LogManager()  // Constructor as Private
    {
        _fileStream = 
File.OpenWrite(GetExecutionFolder() + "\\Application.log");
        _streamWriter = 
new StreamWriter(_fileStream);
    }

 

    private FileStream _fileStream;
    
private StreamWriter _streamWriter;

 

    public void WriteLog(string message)
    {
        
StringBuilder formattedMessage = new StringBuilder();
        formattedMessage.AppendLine(
"Date: " + DateTime.Now.ToString());
        formattedMessage.AppendLine(
"Message: " + message);

        _streamWriter.WriteLine(formattedMessage.ToString());
        _streamWriter.Flush();
    }

 

    public string GetExecutionFolder()
    {
        
return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
    }
}

로거를 Singleton 형태로 구현하였을 때 얻는 이점은 쉽게 떠올릴 수 있습니다.

1. 하나의 인스턴스를 돌려가며 사용하기 때문에 메모리가 절약됩니다.

2. File 접근에 대한 Locking과 그에 따르는 오버헤드를 고려하지 않아도 됩니다.

 

단점도 존재합니다.

1. 멀티-스레딩 환경에서는 약간의 오버헤드를 감수하여야 합니다. (.Net에서는 Thread Safe를 보장합니다 :D)

 

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

C# 멀티코어 프로그래밍  (0) 2012.01.19
[C#] Template Method 패턴  (0) 2012.01.19
[C#] 리플렉션 Reflection  (1) 2012.01.19
[C#] 소멸자 (de-constructor, finalizer)  (0) 2012.01.18
Thread vs ThreadPool  (0) 2012.01.18
posted by 방랑군 2012. 1. 19. 00:27

실행 중에 클래스나 객체의 타입 정보를 조사하는 기능이다.


타입 정보는 보통 컴파일 중에만 사용되며 컴파일러에 의해 기계어로 바뀌고 나면 사라지는 것이 일반적이나 C#은 컴파일된 결과 코드뿐만 아니라 타입에 대한 메타 데이터를 실행 파일에 같이 기록해 놓기 때문에 실행중에도 정보를 조사할 수 있다.


이 기능을 사용하면 실행 중에 다른 모듈에 선언된 인스턴스를 생성할 수 있고 메서드를 호출할 수도 있다.

Type 클래스에서 제공되는 정보로부터 모든 멤버의 정보를 알아낼 수 있기 때문에 실행 중에 클래스 선언문을 통해 복원할 수도 있을 것이다.

 

특정 클래스나 객체의 타입 정보를 조사하고 싶을 때에는 Type 객체를 얻어야 하는데 다음의 세가지 방법으로 얻는다.
------------------------------------------------

// 런타임 시 지정된 이름으로 접근하는 방법

1) Type p = Type.GetType("Top");

 

// 클래스 타입으로 접근하는 방법

2) Type p = tyoeof("Top");

 

// 객체로 접근하는 방법

3) Type p = Top.GetType()

 

Top t = (Top)Activator.CreateInstance(p);

------------------------------------------------

 

// Top 형의 타입에 해당하는 클래스 정보를 Type 형의 객체로 얻어낸다.

// 이 객체 안에 Top 형에 관련된 모든 타입 정보가 들어있다고 보면 된다.

// CLR의 도움 없이 사용자가 직접 핸들하여 객체를 생성하는 것이 된다.

//

// 어셈블리 내에 들어있는 클래스의 타입 정보를 핸들하는 클래스를 Type 클래스라 할 수 있다.

 

  Type 클래스 : 클래스의 정보를 관리하는 클래스라 정의내릴 수 있다.

 

  다음의 예제 코드는, Type 클래스를 이용하여 특정 클래스의 정보를 출력한다.

//////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Reflection;

namespace ReflectionTest1
{
    public class ReflectionTest
    {
        public int temp = 1000;
        public void PrintShow()
        { }

        static void Main(string[] args)
        {
            try
            {
                Type t = Type.GetType("ReflectionTest1.ReflectionTest");

                Console.WriteLine("기본 클래스 타입");
                Console.WriteLine(t.BaseType);

 

                Console.WriteLine("\n생성자 목록");
                ConstructorInfo[] cList = t.GetConstructors();
                foreach (ConstructorInfo c in cList)
                    Console.WriteLine(c);

 

                Console.WriteLine("\n함수 목록");
                MethodInfo[] mList = t.GetMethods();
                foreach (MethodInfo m in mList)
                    Console.WriteLine(m);

 

                Console.WriteLine("\n변수 목록");
                FieldInfo[] fList = t.GetFields();
                foreach (FieldInfo f in fList)
                    Console.WriteLine(f);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}

//////////////////////////////////////////////

 

리플렉션을 사용하지 않은 보통의 경우 우리가 작성한 프로그램은 CLR 내에서 실행되는 프로그램이다.

 

리플렉션을 사용하면 우리는 실행되는 프로그램이 아닌 실행시켜 주는 프로그램까지 만들어낼 수 있다.

 

즉, 미들웨어급 프로그램을 만들어낼 수 있다.

 

출처 : 소설같은 c#

 

## 책에는 리플렉션을 활용한 리플렉션 프로그래밍 기법이 소개되어 있습니다.

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

[C#] Template Method 패턴  (0) 2012.01.19
[C#] Singleton 패턴이 적용된 File 로거  (0) 2012.01.19
[C#] 소멸자 (de-constructor, finalizer)  (0) 2012.01.18
Thread vs ThreadPool  (0) 2012.01.18
마샬링 (Marshaling)  (0) 2012.01.18
posted by 방랑군 2012. 1. 18. 23:16

출처 :   http://blog.naver.com/PostList.nhn?blogId=seokcrew&from=postList&categoryNo=13 

객체가 사라질 때 정리 작업을 수행한다.
생성자와 소멸자는 프레임워크에 의해 자동으로 호출된다.
C#에서는 다른 언어에 비해 소멸자를 잘 사용하지 않으며 필요한 경우도 드물다.
리소스 관리가 가비지 컬렉터에 의해 자동화되어 있기 때문이다.

 

소멸자가 필요한 상황은 프레임워크에 의해 관리되지 않은 리소스를 할당했거나 가비지 컬렉터가 해제할 수 없는 자원을 사용했을 때에 국한된다.


예를 들어 파일을 열어 놓았다거나 네트워크 연결을 해 놓았다면 소멸자에서 이런 비관리 자원을 해제해야 한다.
또는 화면 해상도나 사운드 카드의 볼륨처럼 메모리와 직접적인 상관이 없는 환경을 변경시켰을 때에도 원래대로 복구할 소멸자를 만들 필요가 있다.

 

** 파일 오픈, 권한 획득, 하드웨어 상태 변경 등은 가비지 컬렉터의 능력 밖이다. 이러한 비관리 자원은 최초 자원을 할당한 클래스의 소멸자에서 직접 처리해 주어야 한다.


** 가비지 컬렉터는 백그라운드에서 유휴 시간에 끼어들어 쓰레기 수집을 하므로 동작 시점은 예측할 수 없다. 따라서 객체 소멸 직후에 자원이 바로 해제된다고 보장할 수 없다.

 

** 객체 소멸 시에 리소스를 곧바로 해제하고 싶다면 가비지 컬렉터에 명시적으로 자원 해제를 요구하거나 IDisposable 인터페이스를 상속받아 Dispose 메서드를 구현하여 명시적 호출에 의해 비관리 자원이 해제되게끔 하는 방법을 택하는 것이 옳다. 단, 사용자가 Dispose의 호출을 잊어버릴 수도 있기 때문에 최소한의 방어를 위해 소멸자와 Dispose 메서드를 동시에 구현하는 것이 일반적이다.

 

class Foo : IDisposable
{
    private bool Disposed = false;

 

    public void Dispose()
    {
         Dispose(true);
         GC.SupressFinalize(this);
    }

 

    public virtual void Dispose(bool bManage)
    {
         if (Disposed) return;
         Disposed = true;

 

         if (bManage)
         {
              // 여기서 관리 자원을 해제한다.
         }

             // 여기서 비관리 자원을 해제한다.
     }

 

     ~Foo()
     {
          Dispose(false);
      }
}


 

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

[C#] Singleton 패턴이 적용된 File 로거  (0) 2012.01.19
[C#] 리플렉션 Reflection  (1) 2012.01.19
Thread vs ThreadPool  (0) 2012.01.18
마샬링 (Marshaling)  (0) 2012.01.18
멀티스레드 -> 멀티플렉싱  (0) 2012.01.18
posted by 방랑군 2012. 1. 18. 23:14

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

MS Project 뷰어  (0) 2012.01.18
링크  (0) 2012.01.18
posted by 방랑군 2012. 1. 18. 23:14

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

WPF Datagrid  (0) 2012.01.18
링크  (0) 2012.01.18
posted by 방랑군 2012. 1. 18. 23:13

http://www.silverlight.net/learn/videos/silverlight-4-videos/printing-api-basics/

프린팅 API

 

http://weblogs.asp.net/psheriff/archive/2009/10/29/create-a-login-screen-in-silverlight.aspx

실버라이트 로그인 폼 만들기

 

http://www.vectorlight.net/controls/

실버라이트 컨트롤

 

http://www.visifire.com/

실버라이트 무료 차트 컴포넌트

 

http://www.webresourcesdepot.com/free-silverlight-controls-and-tools-for-brighter-websites/

무료컴포넌트 정리 포스팅

 

http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNO=20&no=713204&ref=713156

스레드 서버 성능 관련

 

http://zzangmyon.tistory.com/category/Blend%20ː%20Silverlight

http://blog.naver.com/im831111

블렌드 관련 참고 사이트


http://michaelsync.net/2008/11/08/silverlight-glass-button

실버라이트 글래스버튼

 

http://www.silverlight.net/learn/videos/silverlight-videos/dataform-control/

how to wcf service in IIS


 

http://msdn.microsoft.com/en-us/library/ms733766.aspx

사용자 정의 ui 컨트롤


 

http://kimgwajang.tistory.com/76

msg box


 

http://www.lyquidity.com/devblog/?p=46

msg board


 

http://openlightgroup.net/Blog/tabid/58/EntryId/67/Silverlight-Message-Board-using-the-CloudDB-com-ldquo-cloud-rdquo-database.aspx

http://openlightgroup.net/Blog/tabid/58/EntryId/106/A-Simple-Silverlight-CRUD-Example.aspx

tcp/ip server


 

http://www.switchonthecode.com/tutorials/csharp-tutorial-simple-threaded-tcp-server

데이터 바인딩


 

http://www.akadia.com/services/dotnet_databinding.html

msdn 라이브러리


 

http://msdn.microsoft.com/ko-kr/library/

linq to sql


 

http://msdn.microsoft.com/ko-kr/library/bb399408(v=VS.90).aspx

wcf-serialization


 

http://vsts2010.net/266

http://www.c-sharpcorner.com/UploadFile/dpatra/386/Default.aspx

http://dpatra.blogspot.com/

 

c-sharpcorner.com
seokcrew@naver.com
F0qtACD

 

http://alomohora.com/multi-page-silverlight-application/

실버라이트 다중 페이지 구현

http://kojaedoo.tistory.com/487

 

http://msdn.microsoft.com/en-us/library/cc296242(VS.95).aspx

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

WPF Datagrid  (0) 2012.01.18
MS Project 뷰어  (0) 2012.01.18
posted by 방랑군 2012. 1. 18. 23:08

Thread pool will provide benefits for frequent and relatively short operations by

  • Reusing threads that have already been created instead of creating new ones (an expensive process)
  • Throttling the rate of thread creation when there is a burst of requests for new work items (I believe this is only in .NET 3.5)

  • If you queue 100 thread pool tasks, it will only use as many threads as have already been created to service these requests (say 10 for example). The thread pool will make frequent checks (I believe every 500ms in 3.5 SP1) and if there are queued tasks, it will make one new thread. If your tasks are quick, then the number of new threads will be small and reusing the 10 or so threads for the short tasks will be faster than creating 100 threads up front.

  • If your workload consistently has large numbers of thread pool requests coming in, then the thread pool will tune itself to your workload by creating more threads in the pool by the above process so that there are a larger number of thread available to process requests

///////////////////

 

스레드풀은 스레드풀에 생성되어 있는 스레드를 재사용하기 때문에,

새로운 스레드 객체를 생성할 때 따르는 오버헤드를 대폭 줄일 수 있다.

 

일반적인 방식으로 스레드를 생성하게 되면

OS 레벨에서는 kernel 객체의 초기화그리고 쓰레드에서 사용되는 stack 메모리의 할당 및 초기화, Windows 운영 체제가 새로운 쓰레드가 생성 될 때 로드 된 assembly에게 DLL_THREAD_ATTACH라는 메시지를 보내기 위해 메모리에 로드 된 페이지의 손실 발생등의 비 효율적인 일들이 벌어집니다.

라고 한다.

 

그러한 비효율을 감소시키는 것이 스레드풀 사용의 목적이라 하겠다.

여기서 한가지 문제가 제기될 수 있다.

 

어플리케이션에서 처리하고자 하는 작업의 수가 시간이 경과하여 줄어든다면, 스레드풀에 있는 필요 이상의 스레드들은 어떻게 될것인가? 하는 문제이다.

하지만 이러한 경우, 스레드풀은 일정 시간동안 휴면상태에 있는 스레드를 반환한다고 한다.

 

즉, 사용상 어떠한 비효율을 일으킬만한 소지는 없어 보인다.

 

스레드풀에서 사용 가능한 스레드의 개수는 cpu spec에 따라 지정되어있고,

사용자가 임의 변경 가능하다.

 

다음과 같은 코드를 통하여,

 

/////

 

maxsync = 100;

 

System.Threading.ThreadPool.SetMaxThreads(maxsync, maxAsync);

 

System.Threading.ThreadPool.GetMaxThreads(out maxsync, out maxAsync);

 

Console.WriteLine("{0},  {1}", maxsync, maxAsync);

 

Console.Read();

 

/////

posted by 방랑군 2012. 1. 18. 23:05

 동일 어플리케이션 도메인에 존재하는 객체의 메서드를 호출할 때의 매개변수나 결과값을 전달할 때

 

에는 스택을 통하여 전달된다. 하지만 동일한 어플리케이션 도메인이 아닌 경우에 서로 다른 스택을

 

사용하기 때문에 객체의 메서드를 호출하거나 결과값을 전달할 때, 스택을 사용할 수 없다. 이러한 경

 

우에 메서드를 호출하기 위하여 사용되는 매개변수는 바이트 스트림(메모리 버퍼)에 기록되고 기록된

 

데이터가 네트워크나 기타 방법을 통하여 전달된다. 이렇게 매개변수나 결과값을 바이트 스트림(메모

 

리 버퍼)로 변환하는 것을 마샬링 이라고 하며, 바이트 스트림(메모리 버퍼)로부터 매개변수나 결과값

 

을 추출하는 것을 언마샬링 이라고 한다.