메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

C# 쓰레드 이야기: 2. 다중 쓰레드

한빛미디어

|

2001-11-10

|

by HANBIT

44,516

by 한동훈(traxacun@unitel.co.kr) 지난 시간(1. 쓰레드는 무엇인가?)에는 간단한 쓰레드를 생성하는 방법에 대해서 살펴보았다. 이번에는 동시에 여러 개의 쓰레드를 다루는 다중 쓰레드에 대해서 알아보자. 여러 개의 쓰레드를 이용하는 프로그램을 작성하는 것은 쉽다. 원하는 수 만큼 쓰레드를 생성하는 프로그램을 작성하기만 하면 된다. 여기서는 하나의 응용프로그램이 세 개의 쓰레드를 갖고 있고, 각각의 쓰레드는 인쇄하기, 저장하기, 철자 검사하기 작업을 시뮬레이션 한다고 가정한다.
namespace csharp
{
  using System;
	using System.Threading;
csharp라는 네임 스페이스를 만든다. 기본 라이브러리인 System 네임 스페이스와 쓰레드를 사용하기 위해 System.Threading 네임 스페이스를 선언한다.
class MultiThreadApp
	{
		public static void Main()
		{	
			MultiThreadApp app = new MultiThreadApp();
			app.DoTest();
		}
클래스 명은 MultiThreadApp로 하고 Main() 메소드에서 MultiThreadApp 클래스의 인스턴스를 하나 생성한다. 그리고 실제 코드는 DoTest() 함수에서 처리하기 때문에 Main()에는 간단한 코드만이 필요하다.
private void DoTest()
{
	Thread t1 = new Thread(
			new ThreadStart(DoPrinting) );

	Thread t2 = new Thread(
			new ThreadStart(DoSpelling) );

	Thread t3 = new Thread(
			new ThreadStart(DoSaving) );

	t1.Start();
	t2.Start();
	t3.Start();
}
먼저 각각의 쓰레드 t1, t2, t3를 만들고, 각 쓰레드에는 DoPrinting, DoSpelling, DoSaving 메소드를 위임한다. 쓰레드의 시작을 위해 각 쓰레드의 Start()를 호출한다. 이제 각각의 쓰레드를 시작하도록 했으므로 각각의 함수 DoPrinting DoSpelling, DoSaving을 살펴보도록 하자.
private void DoPrinting()
{
	Console.WriteLine("인쇄 시작");
	for (int LoopCtr = 0; LoopCtr < 100; LoopCtr++)
	{
		Thread.Sleep(120);
		Console.Write("p|");
	}
	Console.WriteLine("인쇄 완료");
}
먼저 쓰레드를 이용하는 메소드는 void 타입이어야 한다고 설명했었다. 즉, 반환값을 갖지 않는다. 인쇄 시작을 출력하고 100번의 루프를 돌도록 한다. Thread.Sleep(120)은 쓰레드에게 120ms동안 기다리라는 것을 의미하고, 진행중임을 알기 위해 여기서는 루프를 돌 때마다 p|을 출력한다. 그리고 모든 작업이 끝나면 "인쇄 완료"를 출력한다. DoSpelling(), DoSaving()도 이와 같은 역할을 하는 코드이며, 쓰레드를 이용해서 동시에 처리하고 있음을 설명하기 위해 Thread.Sleep()의 시간을 각각 다르게 지정했다. 전체 소스는 다음과 같다.


namespace csharp
{
  using System;
  using System.Threading;

  class MultiThreadApp
  {
    public static void Main()
    {
      MultiThreadApp app = new MultiThreadApp();

      app.DoTest();
    }

    private void DoTest()
    {
      Thread t1 = new Thread(
                    new ThreadStart(DoPrinting) );

      Thread t2 = new Thread(
                    new ThreadStart(DoSpelling) );

      Thread t3 = new Thread(
                    new ThreadStart(DoSaving) );

      t1.Start();
      t2.Start();
      t3.Start();

    }

    private void DoPrinting()
    {
      Console.WriteLine("인쇄 시작");
      for ( int LoopCtr = 0; LoopCtr < 100; LoopCtr++)
      {
        Thread.Sleep(120);
        Console.Write("p|");

      }

      Console.WriteLine("인쇄 완료");
    }

    private void DoSpelling()
    {
      Console.WriteLine("철자 검사 시작");
      for ( int LoopCtr = 0; LoopCtr < 100; LoopCtr++)
      {
        Thread.Sleep(100);
        Console.Write("c|");
      }
      
      Console.WriteLine("철자 검사 완료");
    }

    private void DoSaving()
    {
      Console.WriteLine("저장 시작");
      for ( int LoopCtr = 0; LoopCtr < 100; LoopCtr++)
      {
        Thread.Sleep(50);
        Console.Write("s|");
      }
      Console.WriteLine("저장 완료");
    }
  }

}
이 코드의 컴파일은 다음과 같이한다.
csc /t:exe /out:Multi.exe MultiThreadApp.cs
코드를 실행하면 결과는 다음과 같다.

결과에서 알 수 있는 것처럼 파일을 디스크에 저장하는 작업을 가장 먼저 시작하고(t1), 그 다음에 인쇄 작업(t2), 철자 검사(t3)를 시작한 것을 알 수 있다. 그러나 각각의 작업을 뜻하는 알파벳을 출력하도록 한 결과를 유심히 살펴보면 s|c|s|p|s|c와 같이 각각의 작업이 뒤죽박죽으로 섞여서 동시에 처리되고 있다는 것을 알 수 있을 것이다(Thread.Sleep() 함수에 각각 다른 지연 시간을 지정했기 때문에 이와 같은 결과를 나타낸다. 이 부분을 제거하면 각각의 작업은 같은 비율로 처리 시간을 갖게 될 것이다). 또한 가장 마지막에 시작했던 철자 검사 작업이 두 번째로 끝난다는 것을 알 수 있다. 쓰레드를 동시에 처리하는 것을 조금 더 탐구하고 싶다면 각 Do 함수의 루프 카운터와 Thread.Sleep()의 지연 시간을 바꿔가면서 테스트 해보기 바란다. 다음은 위 예제에서 각각의 쓰레드를 생성해서 처리하던 것을 쓰레드의 배열로 만들어서 보 다 간결하게 쓰레드를 처리하는 예제다. 위 코드에서 DoTest() 함수만 변경되었다.
    private void DoTest()
    {
      Thread[] aThread =
        {
          new Thread( new ThreadStart(DoPrinting) ),
          new Thread( new ThreadStart(DoSpelling) ),
          new Thread( new ThreadStart(DoSaving) )
        };

      foreach( Thread t in aThread)
      {
        t.Start();
      }

    }
다음 단계 다음 시간에는 쓰레드를 종료하는 방법과 예외처리, 백그라운드 처리와 같은 방법에 대해서 알아볼 것이다. 쓰레드에 대한 기본 개념을 코드를 통해서 충분히 연습하고 익힌 다음에는 다중 쓰레드 응용 프로그램에서 발생할 수 있는 많은 문제들에 대해서 살펴볼 때 많은 도움이 될 것이다. 천리길도 한 걸음부터… 우리가 아직 오를 계단은 많이 남아있다. 다음 계단을 오를 때 까지 코드를 변형해보면서 테스트하고, 보다 많은 것들을 살펴보고자 한다면 온라인 도움말을 찾아보기 바란다. 궁금한 사항이 있다면 게시판이나 전자우편으로 질문하기 바란다.
TAG :
댓글 입력
자료실

최근 본 상품0