반응형

*델리 게이트(Delegate)

 - 대리자 로써 C 언어나 C++ 언어 를 공부한 사람이라면 쉽게 접할 수 있는 함수 포인터와

   비슷한 기능을 합니다.  또한 콜백 함수 기능 역할도 수행 

   

*델리 게이트 선언 방법과 간단한 예제

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Delegate
{
    public partial class Form1 : Form
    {
		//델리게이트 선언...
        delegate int delegateFuncA(int a, int b);
        delegate void delegateFuncB(int a, int b);
        delegate string delefageFuncC(int a);

        public Form1()
        {
            InitializeComponent();
        }
		
        //함수 선언...
        private int FuncA(int a, int b)
        {
            return a + b;
        }
        private void FuncB(int a, int b)
        {
            MessageBox.Show((a + b).ToString());
        }
        private string FuncC(int a)
        {
            return (a + 15).ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            delegateFuncA dfa = new delegateFuncA(FuncA); //FuncA 에 대한 델리게이트를 만든다.
            MessageBox.Show(dfa(5, 6).ToString() + " , Delegate 함수 사용");

        }

        private void button2_Click(object sender, EventArgs e)
        {
            delegateFuncB dfa = new delegateFuncB(FuncB); //FuncB 에 대한 델리게이트를 만든다.
        }

        private void button3_Click(object sender, EventArgs e)
        {
            delefageFuncC dfa = new delefageFuncC(FuncC); //FuncC 에 대한 델리게이트를 만든다.
            MessageBox.Show(dfa(5));
        }
    }
}

 

위 코드와 같이 델리 게이트 선언 형식과 함수 형식이 같으며,

(델리게이트 함수 이름은 변수 이름(delegateFuncA,B,C) 사용자 마음대로 지정 가능)

만약 리턴 형식 및 전달 인자 형식이 틀리게 되면 아래의 그림과 같이 오류가 발생 하게 됩니다.

 

 

간략히 델리 게이트가 무엇이며, 간단한 예제를 만들어 봤습니다. 다음 시간에는 실제 델리게이트가 어떻게 사용

되는지 알아 보는 시간을 갖도록 하겠습니다~

반응형
반응형

#region 프로젝트 폼 목록 읽어 오기

        public static Form GetAssemblyForm(string strFormName)
        {
            Form f = null;
            foreach (Type t in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
            {
                if (t.Name == strFormName)                     //프로젝트 내 폼 중에서 찾을 이름과 같으면...
                {
                    object o = Activator.CreateInstance(t);    //인스턴스 개체 생성 
                    f = o as Form;                                  //인스턴스 개체 폼 형식으로 캐스팅
                }
            }
            return f;
        }

        public static List

 GetAssemblyFormList()
        {
            List
 ltForm = new List

();
            foreach (Type t in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
            {
                if (t.BaseType.FullName.ToString() == "System.Windows.Forms.Form")  // 타입이 윈도우즈 폼이면...
                {
                    object o = Activator.CreateInstance(t);                                      //개체 생성
                    Form f = o as Form;                                                            //폼 형식으로 캐스팅
                    ltForm.Add(f);                                                                    //리스트에 담기
                }
            }

            return ltForm;

        }

        #endregion

 

 

 

 

소스 예제...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        #region 프로젝트 폼 목록 읽어 오기

        private Form GetAssemblyForm(string strFormName)
        {
            Form f = null;
            foreach (Type t in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
            {
                if (t.Name == strFormName)
                {
                    object o = Activator.CreateInstance(t);
                    f = o as Form;
                }
            }

            return f;

        }

        private List<Form> GetAssemblyFormList()
        {
            List<Form> ltForm = new List<Form>();

            listBox1.Items.Clear();

            foreach (Type t in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
            {
                if (t.BaseType.FullName.ToString() == "System.Windows.Forms.Form")
                {
                    object o = Activator.CreateInstance(t);
                    Form f = o as Form;
                    ltForm.Add(f);
                }
            }

            return ltForm;

        }

        #endregion


        private void button1_Click(object sender, EventArgs e)
        {
            List<Form> ltList = GetAssemblyFormList();

            for (int iCount = 0; iCount < ltList.Count; iCount++)
            {
                Form f = ltList[iCount] as Form;
                listBox1.Items.Add(f.Text);
            }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Form f = GetAssemblyForm("frmSearch");

            MessageBox.Show(f.Text + " 를 찾았습니다.");
        }
    }
}

 

반응형
반응형

설명

Task 클래스는 반환 하지 않는 값을 지정 하 고는 일반적으로 단일 작업을 비동기적으로 실행 합니다. Task 개체는의 중앙 구성 요소 중 하나는 작업 기반 비동기 패턴 .NET Framework 4에서 처음 도입 된 합니다. 작업을 수행 하므로 Task 개체 일반적으로 비동기적으로 실행 스레드 풀 스레드에서 동기적으로 주 애플리케이션 스레드에서 사용할 수 있습니다 것이 아니라 합니다 Status 속성인 뿐만 IsCanceled, IsCompleted, 및 IsFaulted 속성에는 작업의 상태를 확인 합니다. 가장 일반적으로 작업을 수행 하는 작업을 지정 하는 람다 식 사용 됩니다.

사용할 값을 반환 하는 작업의 경우는 Task<TResult> 클래스입니다.

using System;
using System.Threading;
using System.Threading.Tasks;

class Example
{
    static void Main()
    {
        Action<object> action = (object obj) =>
                                {
                                   Console.WriteLine("Task={0}, obj={1}, Thread={2}",
                                   Task.CurrentId, obj,
                                   Thread.CurrentThread.ManagedThreadId);
                                };

        // Create a task but do not start it.
        Task t1 = new Task(action, "alpha");

        // Construct a started task
        Task t2 = Task.Factory.StartNew(action, "beta");
        // Block the main thread to demonstrate that t2 is executing
        t2.Wait();

        // Launch t1 
        t1.Start();
        Console.WriteLine("t1 has been launched. (Main Thread={0})",
                          Thread.CurrentThread.ManagedThreadId);
        // Wait for the task to finish.
        t1.Wait();

        // Construct a started task using Task.Run.
        String taskData = "delta";
        Task t3 = Task.Run( () => {Console.WriteLine("Task={0}, obj={1}, Thread={2}",
                                                     Task.CurrentId, taskData,
                                                      Thread.CurrentThread.ManagedThreadId);
                                   });
        // Wait for the task to finish.
        t3.Wait();

        // Construct an unstarted task
        Task t4 = new Task(action, "gamma");
        // Run it synchronously
        t4.RunSynchronously();
        // Although the task was run synchronously, it is a good practice
        // to wait for it in the event exceptions were thrown by the task.
        t4.Wait();
    }
}
// The example displays output like the following:
//       Task=1, obj=beta, Thread=3
//       t1 has been launched. (Main Thread=1)
//       Task=2, obj=alpha, Thread=4
//       Task=3, obj=delta, Thread=3
//       Task=4, obj=gamma, Thread=1

분리 작업 만들기 및 실행

Task 클래스는 또한 작업을 초기화 하는 하지만 해당 실행에 대 한 예약 하지 않습니다 하는 생성자를 제공 합니다. 성능상의 이유로 합니다 Task.Run 또는 TaskFactory.StartNew 메서드를 만들고 계산 태스크를 예약 하기 위한 기본 메커니즘입니다 하지만 생성 및 일정 예약을 구분 해야 합니다는 시나리오에 대 한 생성자를 사용 하 여를 호출 합니다 Task.Start 나중에 실행에 대 한 작업을 예약 하는 방법입니다.

 

하나 이상의 작업이 완료 되기를 기다리는

작업 일반적으로 스레드 풀 스레드에서 비동기적으로 실행, 때문에 작업을 인스턴스화해야 하는 즉시 만들고 작업을 시작 하는 스레드 실행을 계속 합니다. 일부 경우에 호출 스레드는 주 애플리케이션 스레드의 경우 앱을 종료할 수 있습니다 보다 먼저 태스크 실제로 실행을 시작 합니다. 다른 애플리케이션의 논리는 하나 이상의 작업 실행을 완료 하는 경우에 호출 스레드가 계속 실행 필요할 수 있습니다. 호출 스레드의 실행을 동기화 할 수 있습니다 및 비동기 작업이 출시를 호출 하 여를 Wait 메서드를 하나 이상의 작업이 완료 될 때까지 기다립니다.

완료 하는 단일 작업에 대 한 대기를 호출 하면 해당 Task.Wait 메서드. 에 대 한 호출을 Wait 메서드는 단일 클래스 인스턴스 실행이 완료 될 때까지 호출 스레드를 차단 합니다.

다음 예제에서는 매개 변수가 없는 호출 Wait() 작업이 완료 될 때까지 무조건 대기 하는 방법입니다. 태스크를 호출 하 여 작업을 시뮬레이트하는 Thread.Sleep 2 초 대기 하는 방법입니다.

 

using System;   
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static Random rand = new Random();

    static void Main()
    {
        // Wait on a single task with no timeout specified.
        Task taskA = Task.Run( () => Thread.Sleep(2000));
        Console.WriteLine("taskA Status: {0}", taskA.Status);
        try {
          taskA.Wait();
          Console.WriteLine("taskA Status: {0}", taskA.Status);
       } 
       catch (AggregateException) {
          Console.WriteLine("Exception in taskA.");
       }   
    }    
}
// The example displays output like the following:
//     taskA Status: WaitingToRun
//     taskA Status: RanToCompletion

또한 조건에 따라 작업이 완료 되기를 기다릴 수 있습니다. 합니다 Wait(Int32)  Wait(TimeSpan) 메서드는 작업이 완료 될 때까지 호출 스레드를 차단 또는 먼저 도달 하는 시간 제한 간격이 경과 합니다. 다음 예제에서는 2 초 동안 대기 하지만 해당 호출 스레드는 차단 시간 제한이 만료 될 때까지 1 초 제한 시간 값을 정의 하는 작업을 시작 하므로 전과 작업 실행이 완료 합니다.

 

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      // Wait on a single task with a timeout specified.
      Task taskA = Task.Run( () => Thread.Sleep(2000));
      try {
        taskA.Wait(1000);       // Wait for 1 second.
        bool completed = taskA.IsCompleted;
        Console.WriteLine("Task A completed: {0}, Status: {1}",
                         completed, taskA.Status);
        if (! completed)
           Console.WriteLine("Timed out before task A completed.");                 
       }
       catch (AggregateException) {
          Console.WriteLine("Exception in taskA.");
       }   
   }
}
// The example displays output like the following:
//     Task A completed: False, Status: Running
//     Timed out before task A completed.

 

호출 하 여 취소 토큰을 제공할 수도 있습니다는 Wait(CancellationToken)  Wait(Int32, CancellationToken) 메서드. 경우 토큰의 IsCancellationRequested 속성은 true 는 더 이상 true 하는 동안 합니다 Wait 메서드를 실행, 메서드가 throw는 OperationCanceledException합니다.

경우에 따라 대기 하려는 싶지만 완료 하는 일련의 작업을 실행 중 첫 번째 작업 하는 주의 해야입니다. 이 위해 수 중 하나를 호출의 오버 로드는 Task.WaitAny 메서드. 다음 예제에서는 난수 생성기에서 간격 결정에 대 한 절전 모드로 전환 되는 각 세 가지 작업을 만듭니다. WaitAny(Task[]) 메서드 첫 번째 작업이 완료 되기를 기다립니다. 다음 예제에서는 세 작업의 상태에 대 한 정보를 표시합니다.

 

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var tasks = new Task[3];
      var rnd = new Random();
      for (int ctr = 0; ctr <= 2; ctr++)
         tasks[ctr] = Task.Run( () => Thread.Sleep(rnd.Next(500, 3000)));

      try {
         int index = Task.WaitAny(tasks);
         Console.WriteLine("Task #{0} completed first.\n", tasks[index].Id);
         Console.WriteLine("Status of all tasks:");
         foreach (var t in tasks)
            Console.WriteLine("   Task #{0}: {1}", t.Id, t.Status);
      }
      catch (AggregateException) {
         Console.WriteLine("An exception occurred.");
      }
   }
}
// The example displays output like the following:
//     Task #1 completed first.
//     
//     Status of all tasks:
//        Task #3: Running
//        Task #1: RanToCompletion
//        Task #4: Running

일련의 작업을 호출 하 여 완료 모든 않을 수도 있습니다는 WaitAll 메서드. 다음 예제에서는 10 개의 작업을 만드는, 대기를 완료 하려면 모든 10에 대 한 다음 해당 상태를 표시 합니다.

 

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      // Wait for all tasks to complete.
      Task[] tasks = new Task[10];
      for (int i = 0; i < 10; i++)
      {
          tasks[i] = Task.Run(() => Thread.Sleep(2000));
      }
      try {
         Task.WaitAll(tasks);
      }
      catch (AggregateException ae) {
         Console.WriteLine("One or more exceptions occurred: ");
         foreach (var ex in ae.Flatten().InnerExceptions)
            Console.WriteLine("   {0}", ex.Message);
      }   

      Console.WriteLine("Status of completed tasks:");
      foreach (var t in tasks)
         Console.WriteLine("   Task #{0}: {1}", t.Id, t.Status);
   }
}
// The example displays the following output:
//     Status of completed tasks:
//        Task #2: RanToCompletion
//        Task #1: RanToCompletion
//        Task #3: RanToCompletion
//        Task #4: RanToCompletion
//        Task #6: RanToCompletion
//        Task #5: RanToCompletion
//        Task #7: RanToCompletion
//        Task #8: RanToCompletion
//        Task #9: RanToCompletion
//        Task #10: RanToCompletion

 

하나 이상의 작업이 완료 되기를 기다릴 때 호출 하는 스레드에서 실행 중인 작업에서 throw 된 예외 전파는 참고를 Wait 메서드를 다음 예제와 같이 합니다. 정상적으로 완료 중 3 개는 12 작업 및 세 가지 예외는 throw를 시작 합니다. 나머지 6 개 작업 중 세 개는 시작 하기 전에 취소 되 고 3은 실행 중에 취소 됩니다. 예외가 throw 되는 WaitAll 에 의해 처리 되며 메서드 호출을 try / catch 블록입니다.

 

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      // Create a cancellation token and cancel it.
      var source1 = new CancellationTokenSource();
      var token1 = source1.Token;
      source1.Cancel();
      // Create a cancellation token for later cancellation.
      var source2 = new CancellationTokenSource();
      var token2 = source2.Token;
       
      // Create a series of tasks that will complete, be cancelled, 
      // timeout, or throw an exception.
      Task[] tasks = new Task[12];
      for (int i = 0; i < 12; i++)
      {
          switch (i % 4) 
          {
             // Task should run to completion.
             case 0:
                tasks[i] = Task.Run(() => Thread.Sleep(2000));
                break;
             // Task should be set to canceled state.
             case 1:   
                tasks[i] = Task.Run( () => Thread.Sleep(2000),
                         token1);
                break;         
             case 2:
                // Task should throw an exception.
                tasks[i] = Task.Run( () => { throw new NotSupportedException(); } );
                break;
             case 3:
                // Task should examine cancellation token.
                tasks[i] = Task.Run( () => { Thread.Sleep(2000); 
                                             if (token2.IsCancellationRequested)
                                                token2.ThrowIfCancellationRequested();
                                             Thread.Sleep(500); }, token2);   
                break;
          }
      }
      Thread.Sleep(250);
      source2.Cancel();
       
      try {
         Task.WaitAll(tasks);
      }
      catch (AggregateException ae) {
          Console.WriteLine("One or more exceptions occurred:");
          foreach (var ex in ae.InnerExceptions)
             Console.WriteLine("   {0}: {1}", ex.GetType().Name, ex.Message);
       }   

      Console.WriteLine("\nStatus of tasks:");
      foreach (var t in tasks) {
         Console.WriteLine("   Task #{0}: {1}", t.Id, t.Status);
         if (t.Exception != null) {
            foreach (var ex in t.Exception.InnerExceptions)
               Console.WriteLine("      {0}: {1}", ex.GetType().Name,
                                 ex.Message);
         }
      }
   }
}
// The example displays output like the following:
//   One or more exceptions occurred:
//      TaskCanceledException: A task was canceled.
//      NotSupportedException: Specified method is not supported.
//      TaskCanceledException: A task was canceled.
//      TaskCanceledException: A task was canceled.
//      NotSupportedException: Specified method is not supported.
//      TaskCanceledException: A task was canceled.
//      TaskCanceledException: A task was canceled.
//      NotSupportedException: Specified method is not supported.
//      TaskCanceledException: A task was canceled.
//   
//   Status of tasks:
//      Task #13: RanToCompletion
//      Task #1: Canceled
//      Task #3: Faulted
//         NotSupportedException: Specified method is not supported.
//      Task #8: Canceled
//      Task #14: RanToCompletion
//      Task #4: Canceled
//      Task #6: Faulted
//         NotSupportedException: Specified method is not supported.
//      Task #7: Canceled
//      Task #15: RanToCompletion
//      Task #9: Canceled
//      Task #11: Faulted
//         NotSupportedException: Specified method is not supported.
//      Task #12: Canceled

작업 기반 비동기 작업에서 예외 처리에 대 한 자세한 내용은 참조 하세요. 예외 처리합니다.

 

* 참고 https://docs.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.task?view=netframework-4.8

반응형
반응형

BackgroundWorker 클래스를 사용 하면 별도 전용 스레드에서 작업을 실행할 수 있습니다. 다운로드 및 데이터베이스 트랜잭션과 같은 시간이 많이 걸리는 작업은 사용자 인터페이스 (UI) 실행 하 고 응답을 멈춘 것 처럼 보일 수 발생할 수 있습니다. 이러한 작업으로 인 한 지연이 길어지는 경우 및 응답성이 뛰어난 UI를 구성할 때의 BackgroundWorker 클래스는 편리 하 게 솔루션을 제공 합니다.

시간이 많이 걸리는 작업을 백그라운드에서를 실행 하려면 만들기를 BackgroundWorker 작업이 완료 되 면 신호 확인 하 고 작업의 진행률을 보고 하는 이벤트를 수신 합니다. 만들 수 있습니다는 BackgroundWorker 프로그래밍 방식으로에서 폼으로 끌어 놓을 수 있습니다 합니다 구성 요소 탭의 도구 상자. 만드는 경우는 BackgroundWorker Windows Forms 디자이너에서 구성 요소 트레이에 표시 됩니다 하 고 해당 속성이 속성 창에 표시 됩니다.

백그라운드 작업에 대 한 설정에 대 한 이벤트 처리기를 추가 합니다 DoWork 이벤트입니다. 이 이벤트 처리기에서 시간이 오래 걸리는 작업을 호출 합니다. 작업을 시작 하려면 호출 RunWorkerAsync합니다. 진행률 업데이트의 알림을 받으려면 처리는 ProgressChanged 이벤트입니다. 작업이 완료 될 때 알림을 받으려면 처리는 RunWorkerCompleted 이벤트입니다.

Background Worker 속성
BackgroundWorker 이벤트

예제

다음 코드 예제는 기본 사항을 보여줍니다는 BackgroundWorker 시간이 많이 걸리는 작업을 비동기적으로 실행 하기 위한 클래스입니다. 다음 그림에서는 출력의 예를 보여 줍니다.

이 코드를 실행 하려면 Windows Forms 애플리케이션을 작성 합니다. 추가 Label 라는 컨트롤 resultLabel 두 개의 추가 Button 컨트롤 이라는 startAsyncButton  cancelAsyncButton합니다. 만들 Click 두 단추에 대 한 이벤트 처리기입니다. 구성 요소 탭 도구 상자의 추가 BackgroundWorker 라는 구성 요소 backgroundWorker1합니다. 만들 DoWork, ProgressChanged, 및 RunWorkerCompleted 에 대 한 이벤트 처리기는 BackgroundWorker합니다. 폼의 코드에서 기존 코드를 다음 코드로 바꿉니다.

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace BackgroundWorkerSimple
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
        }

        private void startAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy != true)
            {
                // Start the asynchronous operation.
                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void cancelAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.WorkerSupportsCancellation == true)
            {
                // Cancel the asynchronous operation.
                backgroundWorker1.CancelAsync();
            }
        }

        // This event handler is where the time-consuming work is done.
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 1; i <= 10; i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(500);
                    worker.ReportProgress(i * 10);
                }
            }
        }

        // This event handler updates the progress.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            resultLabel.Text = (e.ProgressPercentage.ToString() + "%");
        }

        // This event handler deals with the results of the background operation.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true)
            {
                resultLabel.Text = "Canceled!";
            }
            else if (e.Error != null)
            {
                resultLabel.Text = "Error: " + e.Error.Message;
            }
            else
            {
                resultLabel.Text = "Done!";
            }
        }
    }
}

 

*참고 : https://docs.microsoft.com/ko-kr/dotnet/api/system.componentmodel.backgroundworker?view=netframework-4.8

반응형
반응형

이 예제에서는 보조 또는 작업자 스레드를 만들고 기본 스레드와 함께 이 스레드를 병렬로 사용하여 작업 처리를 수행하는 방법을 보여 줍니다. 또한 다른 스레드의 작업이 끝날 때까지 한 스레드가 대기하도록 만들고 스레드를 올바르게 종료하는 방법도 보여 줍니다. 다중 스레딩에 대한 배경 정보는 관리되는 스레딩  스레딩 사용(C# 프로그래밍 가이드)을 참조.

 

Worker 클래스에는 DoWork에 반환할 시기를 알리는 데 사용되는 추가 메서드가 포함됩니다. RequestStop이라는 이 메서드는 다음과 같습니다.

 

RequestStop 메서드는 _shouldStop 데이터 멤버를 true로 할당하기만 합니다. 이 데이터 멤버는 DoWork 메서드에서 검사하므로 이는 간접적으로 DoWork가 반환되도록 하여 결과적으로 작업자 스레드가 종료됩니다. 그러나 중요한 점은 DoWork와 RequestStop이 서로 다른 스레드에서 실행된다는 사실입니다. DoWork는 작업자 스레드에서 실행되고 RequestStop은 기본 스레드에서 실행되므로 _shouldStop 데이터 멤버는 다음과 같이 volatile로 선언됩니다.

 

volatile 키워드는 여러 스레드가 _shouldStop 데이터 멤버에 액세스하므로 이 멤버의 상태에 대한 최적화 가정을 하지 말아야 한다는 사실을 컴파일러에 경고로 알립니다. 자세한 내용은 volatile(C# 참조)을 참조

 

 

Abort를 호출하여 다른 스레드에서 스레드를 종료할 수도 있습니다. 이 방법을 사용하면 스레드의 작업이 완료되었는지 여부와 관계없이 스레드가 종료되어 리소스를 정리할 수도 없습니다. 따라서 이 예제에서 설명하는 방법을 사용하는 것이 더 좋습니다.

마지막으로, Main 함수가 작업자 스레드 개체에 대한 Join 메서드를 호출하니다. 이 메서드는 개체가 가리키는 스레드가 종료될 때까지 현재 스레드를 차단하거나 대기 상태로 만듭니다. 따라서 Join은 작업자 스레드가 반환되고 자체 종료될 때까지 반환되지 않습니다.

 

이 단계에서는 Main을 실행하는 기본 스레드만 남게 됩니다. 이 스레드는 최종 메시지 하나를 표시한 다음 반환되고 종료됩니다.

 

= 출력 =

main thread: starting worker thread...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: working...
worker thread: terminating gracefully...
main thread: worker thread has terminated

반응형
반응형

* MSDN 내용

방법: 스레드 풀 사용(C# 프로그래밍 가이드)

"스레드 풀"은 백그라운드에서 여러 가지 작업을 수행하는 데 사용할 수 있는 스레드의 컬렉션입니다. 백그라운드에 대한 자세한 내용은 스레딩 사용을 참조하십시오. 스레드 풀을 사용하면 기본 스레드에서 다른 작업을 비동기적으로 수행할 수 있습니다.

스레드 풀은 대개 서버 응용 프로그램에 사용됩니다. 들어오는 각 요청은 스레드 풀의 스레드에 할당되므로 기본 스레드를 사용할 수 있을 때까지 기다리거나 이후의 요청을 처리하는데 시간을 지연하지 않고 요청을 비동기적으로 처리할 수 있습니다.

풀에 있는 스레드가 해당 작업을 완료하고 대기 스레드의 큐로 반환되면 여기서 해당 스레드를 다시 사용할 수 있습니다. 이와 같이 스레드를 다시 사용하면 응용 프로그램에서 각 작업에 대해 새 스레드를 만드느라 리소스를 낭비하지 않아도 됩니다.

스레드 풀에는 일반적으로 스레드의 최대 수가 지정되어 있습니다. 모든 스레드에서 작업을 수행 중이면 다른 작업은 사용 가능한 스레드가 생길 때까지 큐에 배치됩니다.

고유한 스레드 풀을 구현할 수도 있지만 ThreadPool 클래스를 통해 .NET Framework에서 제공하는 스레드 풀을 사용하는 것이 더 간편합니다.

다음 예제에서는 .NET Framework 스레드 풀을 사용하여 20과 40 사이의 숫자 10개에 대한 Fibonacci 결과를 계산합니다. 각 Fibonacci 결과는 Fibonacci 클래스로 표현됩니다. 이 클래스는 계산을 수행하는 ThreadPoolCallback이라는 메서드를 제공합니다. 각 Fibonacci 값을 나타내는 개체가 작성되고 ThreadPoolCallback 메서드가 QueueUserWorkItem에 전달되면 이 메서드를 실행하기 위해 풀의 사용 가능한 스레드가 할당됩니다.

 Fibonacci 개체는 계산을 위해 어느 정도 임의로 지정되는 값이고 10개의 스레드는 각각 프로세서 시간을 할당받기 위해 경쟁하므로 10개의 결과를 모두 계산하는 데 얼마나 오래 걸릴지 미리 알 수 없습니다. 생성 과정에서 각 Fibonacci 개체가 ManualResetEvent 클래스의 인스턴스에 전달되는 이유는 바로 여기에 있습니다. 각 개체는 해당 계산이 완료되면 제공된 이벤트 개체에 신호를 보내므로 10개의 Fibonacci 개체가 모두 결과를 계산할 때까지 기본 스레드에서 WaitAll을 사용한 실행을 차단할 수 있습니다. 그런 다음 Main 메서드에서 각 Fibonacci 결과를 표시합니다.


샘플 출력

launching 10 tasks...

result calculated...

result calculated...

result calculated...

result calculated...

result calculated...

result calculated...

result calculated...

result calculated...

result calculated...

result calculated...

all calculations complete

Fibonacci(22) = 17711

Fibonacci(25) = 75025

Fibonacci(32) = 2178309

Fibonacci(36) = 14930352

Fibonacci(32) = 2178309

Fibonacci(26) = 121393

Fibonacci(35) = 9227465

Fibonacci(23) = 28657

Fibonacci(39) = 63245986

Fibonacci(22) = 17711

반응형
반응형

== WM 상수값 정리 ==

 

private const UInt32 WM_ACTIVATE                   = 0x0006;
private const UInt32 WM_ACTIVATEAPP              = 0x001C;
private const UInt32 WM_AFXFIRST                   = 0x0360;
private const UInt32 WM_AFXLAST                    = 0x037F;
private const UInt32 WM_APP                          = 0x8000;
private const UInt32 WM_ASKCBFORMATNAME   = 0x030C;
private const UInt32 WM_CANCELJOURNAL        = 0x004B;
private const UInt32 WM_CANCELMODE             = 0x001F;
private const UInt32 WM_CAPTURECHANGED      = 0x0215;
private const UInt32 WM_CHANGECBCHAIN        = 0x030D;
private const UInt32 WM_CHANGEUISTATE          = 0x0127;
private const UInt32 WM_CHAR                        = 0x0102;
private const UInt32 WM_CHARTOITEM              = 0x002F;
private const UInt32 WM_CHILDACTIVATE           = 0x0022;
private const UInt32 WM_CLEAR                       = 0x0303;
private const UInt32 WM_CLOSE                       = 0x0010;
private const UInt32 WM_COMMAND                = 0x0111;
private const UInt32 WM_COMPACTING             = 0x0041;
private const UInt32 WM_COMPAREITEM            = 0x0039;
private const UInt32 WM_CONTEXTMENU           = 0x007B;
private const UInt32 WM_COPY                        = 0x0301;
private const UInt32 WM_COPYDATA                  = 0x004A;
private const UInt32 WM_CREATE                     = 0x0001;
private const UInt32 WM_CTLCOLORBTN        = 0x0135;
private const UInt32 WM_CTLCOLORDLG        = 0x0136;
private const UInt32 WM_CTLCOLOREDIT       = 0x0133;
private const UInt32 WM_CTLCOLORLISTBOX    = 0x0134;
private const UInt32 WM_CTLCOLORMSGBOX     = 0x0132;
private const UInt32 WM_CTLCOLORSCROLLBAR      = 0x0137;
private const UInt32 WM_CTLCOLORSTATIC     = 0x0138;
private const UInt32 WM_CUT            = 0x0300;
private const UInt32 WM_DEADCHAR           = 0x0103;
private const UInt32 WM_DELETEITEM         = 0x002D;
private const UInt32 WM_DESTROY        = 0x0002;
private const UInt32 WM_DESTROYCLIPBOARD       = 0x0307;
private const UInt32 WM_DEVICECHANGE       = 0x0219;
private const UInt32 WM_DEVMODECHANGE      = 0x001B;
private const UInt32 WM_DISPLAYCHANGE      = 0x007E;
private const UInt32 WM_DRAWCLIPBOARD      = 0x0308;
private const UInt32 WM_DRAWITEM           = 0x002B;
private const UInt32 WM_DROPFILES          = 0x0233;
private const UInt32 WM_ENABLE         = 0x000A;
private const UInt32 WM_ENDSESSION         = 0x0016;
private const UInt32 WM_ENTERIDLE          = 0x0121;
private const UInt32 WM_ENTERMENULOOP      = 0x0211;
private const UInt32 WM_ENTERSIZEMOVE      = 0x0231;
private const UInt32 WM_ERASEBKGND         = 0x0014;
private const UInt32 WM_EXITMENULOOP       = 0x0212;
private const UInt32 WM_EXITSIZEMOVE       = 0x0232;
private const UInt32 WM_FONTCHANGE         = 0x001D;
private const UInt32 WM_GETDLGCODE         = 0x0087;
private const UInt32 WM_GETFONT        = 0x0031;
private const UInt32 WM_GETHOTKEY          = 0x0033;
private const UInt32 WM_GETICON        = 0x007F;
private const UInt32 WM_GETMINMAXINFO      = 0x0024;
private const UInt32 WM_GETOBJECT          = 0x003D;
private const UInt32 WM_GETTEXT        = 0x000D;
private const UInt32 WM_GETTEXTLENGTH      = 0x000E;
private const UInt32 WM_HANDHELDFIRST      = 0x0358;
private const UInt32 WM_HANDHELDLAST       = 0x035F;
private const UInt32 WM_HELP           = 0x0053;
private const UInt32 WM_HOTKEY         = 0x0312;
private const UInt32 WM_HSCROLL        = 0x0114;
private const UInt32 WM_HSCROLLCLIPBOARD       = 0x030E;
private const UInt32 WM_ICONERASEBKGND     = 0x0027;
private const UInt32 WM_IME_CHAR           = 0x0286;
private const UInt32 WM_IME_COMPOSITION    = 0x010F;
private const UInt32 WM_IME_COMPOSITIONFULL    = 0x0284;
private const UInt32 WM_IME_CONTROL        = 0x0283;
private const UInt32 WM_IME_ENDCOMPOSITION     = 0x010E;
private const UInt32 WM_IME_KEYDOWN        = 0x0290;
private const UInt32 WM_IME_KEYLAST        = 0x010F;
private const UInt32 WM_IME_KEYUP          = 0x0291;
private const UInt32 WM_IME_NOTIFY         = 0x0282;
private const UInt32 WM_IME_REQUEST        = 0x0288;
private const UInt32 WM_IME_SELECT         = 0x0285;
private const UInt32 WM_IME_SETCONTEXT     = 0x0281;
private const UInt32 WM_IME_STARTCOMPOSITION   = 0x010D;
private const UInt32 WM_INITDIALOG         = 0x0110;
private const UInt32 WM_INITMENU           = 0x0116;
private const UInt32 WM_INITMENUPOPUP      = 0x0117;
private const UInt32 WM_INPUTLANGCHANGE    = 0x0051;
private const UInt32 WM_INPUTLANGCHANGEREQUEST = 0x0050;
private const UInt32 WM_KEYDOWN        = 0x0100;
private const UInt32 WM_KEYFIRST           = 0x0100;
private const UInt32 WM_KEYLAST        = 0x0108;
private const UInt32 WM_KEYUP          = 0x0101;
private const UInt32 WM_KILLFOCUS          = 0x0008;
private const UInt32 WM_LBUTTONDBLCLK      = 0x0203;
private const UInt32 WM_LBUTTONDOWN        = 0x0201;
private const UInt32 WM_LBUTTONUP          = 0x0202;
private const UInt32 WM_MBUTTONDBLCLK      = 0x0209;
private const UInt32 WM_MBUTTONDOWN        = 0x0207;
private const UInt32 WM_MBUTTONUP          = 0x0208;
private const UInt32 WM_MDIACTIVATE        = 0x0222;
private const UInt32 WM_MDICASCADE         = 0x0227;
private const UInt32 WM_MDICREATE          = 0x0220;
private const UInt32 WM_MDIDESTROY         = 0x0221;
private const UInt32 WM_MDIGETACTIVE       = 0x0229;
private const UInt32 WM_MDIICONARRANGE     = 0x0228;
private const UInt32 WM_MDIMAXIMIZE        = 0x0225;
private const UInt32 WM_MDINEXT        = 0x0224;
private const UInt32 WM_MDIREFRESHMENU     = 0x0234;
private const UInt32 WM_MDIRESTORE         = 0x0223;
private const UInt32 WM_MDISETMENU         = 0x0230;
private const UInt32 WM_MDITILE        = 0x0226;
private const UInt32 WM_MEASUREITEM        = 0x002C;
private const UInt32 WM_MENUCHAR           = 0x0120;
private const UInt32 WM_MENUCOMMAND        = 0x0126;
private const UInt32 WM_MENUDRAG           = 0x0123;
private const UInt32 WM_MENUGETOBJECT      = 0x0124;
private const UInt32 WM_MENURBUTTONUP      = 0x0122;
private const UInt32 WM_MENUSELECT         = 0x011F;
private const UInt32 WM_MOUSEACTIVATE      = 0x0021;
private const UInt32 WM_MOUSEFIRST         = 0x0200;
private const UInt32 WM_MOUSEHOVER         = 0x02A1;
private const UInt32 WM_MOUSELAST          = 0x020D;
private const UInt32 WM_MOUSELEAVE         = 0x02A3;
private const UInt32 WM_MOUSEMOVE          = 0x0200;
private const UInt32 WM_MOUSEWHEEL         = 0x020A;
private const UInt32 WM_MOUSEHWHEEL        = 0x020E;
private const UInt32 WM_MOVE           = 0x0003;
private const UInt32 WM_MOVING         = 0x0216;
private const UInt32 WM_NCACTIVATE         = 0x0086;
private const UInt32 WM_NCCALCSIZE         = 0x0083;
private const UInt32 WM_NCCREATE           = 0x0081;
private const UInt32 WM_NCDESTROY          = 0x0082;
private const UInt32 WM_NCHITTEST          = 0x0084;
private const UInt32 WM_NCLBUTTONDBLCLK    = 0x00A3;
private const UInt32 WM_NCLBUTTONDOWN      = 0x00A1;
private const UInt32 WM_NCLBUTTONUP        = 0x00A2;
private const UInt32 WM_NCMBUTTONDBLCLK    = 0x00A9;
private const UInt32 WM_NCMBUTTONDOWN      = 0x00A7;
private const UInt32 WM_NCMBUTTONUP        = 0x00A8;
private const UInt32 WM_NCMOUSEHOVER       = 0x02A0;
private const UInt32 WM_NCMOUSELEAVE       = 0x02A2;
private const UInt32 WM_NCMOUSEMOVE        = 0x00A0;
private const UInt32 WM_NCPAINT        = 0x0085;
private const UInt32 WM_NCRBUTTONDBLCLK    = 0x00A6;
private const UInt32 WM_NCRBUTTONDOWN      = 0x00A4;
private const UInt32 WM_NCRBUTTONUP        = 0x00A5;
private const UInt32 WM_NCXBUTTONDBLCLK    = 0x00AD;
private const UInt32 WM_NCXBUTTONDOWN      = 0x00AB;
private const UInt32 WM_NCXBUTTONUP        = 0x00AC;
private const UInt32 WM_NCUAHDRAWCAPTION       = 0x00AE;
private const UInt32 WM_NCUAHDRAWFRAME     = 0x00AF;
private const UInt32 WM_NEXTDLGCTL         = 0x0028;
private const UInt32 WM_NEXTMENU           = 0x0213;
private const UInt32 WM_NOTIFY         = 0x004E;
private const UInt32 WM_NOTIFYFORMAT       = 0x0055;
private const UInt32 WM_NULL           = 0x0000;
private const UInt32 WM_PAINT          = 0x000F;
private const UInt32 WM_PAINTCLIPBOARD     = 0x0309;
private const UInt32 WM_PAINTICON          = 0x0026;
private const UInt32 WM_PALETTECHANGED     = 0x0311;
private const UInt32 WM_PALETTEISCHANGING      = 0x0310;
private const UInt32 WM_PARENTNOTIFY       = 0x0210;
private const UInt32 WM_PASTE          = 0x0302;
private const UInt32 WM_PENWINFIRST        = 0x0380;
private const UInt32 WM_PENWINLAST         = 0x038F;
private const UInt32 WM_POWER          = 0x0048;
private const UInt32 WM_POWERBROADCAST     = 0x0218;
private const UInt32 WM_PRINT          = 0x0317;
private const UInt32 WM_PRINTCLIENT        = 0x0318;
private const UInt32 WM_QUERYDRAGICON      = 0x0037;
private const UInt32 WM_QUERYENDSESSION    = 0x0011;
private const UInt32 WM_QUERYNEWPALETTE    = 0x030F;
private const UInt32 WM_QUERYOPEN          = 0x0013;
private const UInt32 WM_QUEUESYNC          = 0x0023;
private const UInt32 WM_QUIT           = 0x0012;
private const UInt32 WM_RBUTTONDBLCLK      = 0x0206;
private const UInt32 WM_RBUTTONDOWN        = 0x0204;
private const UInt32 WM_RBUTTONUP          = 0x0205;
private const UInt32 WM_RENDERALLFORMATS       = 0x0306;
private const UInt32 WM_RENDERFORMAT       = 0x0305;
private const UInt32 WM_SETCURSOR          = 0x0020;
private const UInt32 WM_SETFOCUS           = 0x0007;
private const UInt32 WM_SETFONT        = 0x0030;
private const UInt32 WM_SETHOTKEY          = 0x0032;
private const UInt32 WM_SETICON        = 0x0080;
private const UInt32 WM_SETREDRAW          = 0x000B;
private const UInt32 WM_SETTEXT        = 0x000C;
private const UInt32 WM_SETTINGCHANGE      = 0x001A;
private const UInt32 WM_SHOWWINDOW         = 0x0018;
private const UInt32 WM_SIZE           = 0x0005;
private const UInt32 WM_SIZECLIPBOARD      = 0x030B;
private const UInt32 WM_SIZING         = 0x0214;
private const UInt32 WM_SPOOLERSTATUS      = 0x002A;
private const UInt32 WM_STYLECHANGED       = 0x007D;
private const UInt32 WM_STYLECHANGING      = 0x007C;
private const UInt32 WM_SYNCPAINT          = 0x0088;
private const UInt32 WM_SYSCHAR        = 0x0106;
private const UInt32 WM_SYSCOLORCHANGE     = 0x0015;
private const UInt32 WM_SYSCOMMAND         = 0x0112;
private const UInt32 WM_SYSDEADCHAR        = 0x0107;
private const UInt32 WM_SYSKEYDOWN         = 0x0104;
private const UInt32 WM_SYSKEYUP           = 0x0105;
private const UInt32 WM_TCARD          = 0x0052;
private const UInt32 WM_TIMECHANGE         = 0x001E;
private const UInt32 WM_TIMER          = 0x0113;
private const UInt32 WM_UNDO           = 0x0304;
private const UInt32 WM_UNINITMENUPOPUP    = 0x0125;
private const UInt32 WM_USER           = 0x0400;
private const UInt32 WM_USERCHANGED        = 0x0054;
private const UInt32 WM_VKEYTOITEM         = 0x002E;
private const UInt32 WM_VSCROLL        = 0x0115;
private const UInt32 WM_VSCROLLCLIPBOARD       = 0x030A;
private const UInt32 WM_WINDOWPOSCHANGED       = 0x0047;
private const UInt32 WM_WINDOWPOSCHANGING      = 0x0046;
private const UInt32 WM_WININICHANGE       = 0x001A;
private const UInt32 WM_XBUTTONDBLCLK      = 0x020D;
private const UInt32 WM_XBUTTONDOWN        = 0x020B;
private const UInt32 WM_XBUTTONUP          = 0x020C;

반응형
반응형

*String 클래스가 제공하는 메서드 
Ex.)
string str = "가나다라마바사";

//문자열 "라마바" 를 찾아 "Magic"으로 변환
console.writeline("{0}", str.Replace("라마바", "Magic"));

 

//2번째 위치에 "ABC" 삽입
console.writeline("{0}", str.Insert(2, "ABC"));

 

//문자열 3번 위치에서 3문자만큼 제거
console.writeline("{0}", str.Remove(3,3));

 

//str 문자 와 입력한 문자열이 같으면 0 , str 크면 양수 , 작으면 음수 반환
if(str.CompareTo("가나다라마바사") == 0) // CompareTo 안에 문자열이 입력 문자열

 

// 특정 문자열 기준으로 문자열을 짜름
string[] strTmp;
strTmp = str.Split("다");

 

//데이터를 16진수로 만들기
string strTmp="";
string.Format("{0:x2}", 16);

 

//스트링을 구분자로 쪼겠다가 다시 구분자로 합치기
string wStr = "1,2,3,4,5,6,7,8,9,0";
string[] sTmp = wStr.Split(',');        // STmp[0] = 1,STmp[1] = 2,STmp[2] = 3,....
string sTmp1 = string.join(",",sTmp);  // sTmp1 = "1,2,3,4,5,6,7,8,9,0"

 

* 날짜 표현

String.Format(@"{0:yyyy-MM-dd}", DateTime.Now); // 2009-01-30

String.Format(@"{0:tt hh:mm:ss}", DateTime.Now); // 오전 01:47:33

String.Format(@"{0:yyyy-MM-dd tt hh:mm:ss}", DateTime.Now); // 2009-01-30 오전 01:48:11*통화 금액 표현 하기

String.Format(CultureInfo.GetCultureInfo("es-ES"), "{0:C}", 300); // 300,00€

String.Format(CultureInfo.GetCultureInfo("ko-KR"), "{0:C}", 300); // \300


* 진수 표현

"0x" + (16).ToString("X8"); // 8자리 16진수 표기, 대문자

"0x" + (33).ToString("x4"); // 4자리 16진수 표기, 소문자

반응형

+ Recent posts