블로그 이미지
따시쿵

calendar

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

Notice

2015. 3. 2. 17:16 C#

프로그램 설명


BackgroundWorker 클래스를 이용한 프로그램을 만들어 봤습니다.


두 가지 방법으로 만들었는데,

첫번째 방법은 도구 상자에서 Background 컴포넌트를 디자인 화면에 드래그하는 방법과 두번째는 스크립트로 직접 타이핑을 하는 방법으로 개발했습니다.


첫번째 프로그램에 thread id 를 Debug 시에 출력을 해서 어떤 method 가 ui thread와 다르게 운영되는지 확인 해 보았습니다. 예상한대로 DoWork method 가 ui thread와 다르네요.


new Thread와 비교를 해보면 화면 출력을 편리하게 할 수 있고, 진행 상황을 확인해야 하는 프로그램에 적용하면 편리하게 사용이 가능할 듯 합니다.

 

실행 후





프로그램 작성


1. 첫번째 프로그램


        public MainForm()
        {
            InitializeComponent();

            Debug.WriteLine("MainForm() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }

        #region start buton click method
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy)
                label2.Text = "Busy processing, please waiting!!!!";
            else
                backgroundWorker1.RunWorkerAsync();

            Debug.WriteLine("btnStart_Click() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }
        #endregion
             
        #region cancel buton click method
        private void btnCalcel_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy)
                backgroundWorker1.CancelAsync();
            else
                label2.Text = "No cancel processing !!!";

            Debug.WriteLine("btnCalcel_Click() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }
        #endregion

        #region backgroundworker DoWork event
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            Debug.WriteLine("backgroundWorker1_DoWork() thread id : {0}", Thread.CurrentThread.ManagedThreadId);

            int sum = 0;
            for(int i = 0; i<= 100; i++)
            {
                simulateHeavyWork();
                sum += i;
                backgroundWorker1.ReportProgress(i);

                if (backgroundWorker1.CancellationPending)
                {
                    e.Cancel = true;
                    backgroundWorker1.ReportProgress(0);
                    return;
                }
            }

            e.Result = sum;
        }
        #endregion

        #region simulate heavy work
        private void simulateHeavyWork()
        {
            Thread.Sleep(100);
        }
        #endregion

        #region backgroundworker ProgressChanged event
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            label1.Text = e.ProgressPercentage.ToString() + " %";

            Debug.WriteLine("ProgressChanged() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }
        #endregion

        #region backgroundworker RunWorkerCompleted event
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
                label1.Text = "Processing cancelled";
            else if (e.Error != null)
                label1.Text = e.Error.Message;
            else
                label1.Text = "Sum = " + e.Result.ToString();

            Debug.WriteLine("backgroundWorker1_RunWorkerCompleted() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }
        #endregion

        #region program close
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion

 


2. 두번째 프로그램


        private BackgroundWorker myWorker = null;

        #region MainForm() - BackgroundWorker create
        public MainForm()
        {
            InitializeComponent();
            myWorker = new BackgroundWorker();

            myWorker.WorkerReportsProgress = true;
            myWorker.WorkerSupportsCancellation = true;

            myWorker.DoWork += new DoWorkEventHandler(myWork_DoWork);
            myWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
            myWorker.ProgressChanged += new ProgressChangedEventHandler(myWorker_ProgressChanged);
        }
        #endregion

        #region backgroundworker DoWork event
        void myWork_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker sendingWorker = sender as BackgroundWorker;
            object[] arrObjects = e.Argument as object[];

            int maxValue = (int)arrObjects[0];
            StringBuilder sb = new StringBuilder();

            float percentage = 0;
            for (int i = 0; i <= maxValue; i++)
            {
                sb.Append(string.Format("Counting number : {0}{1}", PerformHeavyOperation(i), Environment.NewLine));
                percentage = 100 / (float)maxValue * i;
                sendingWorker.ReportProgress((int)percentage);

                if (sendingWorker.CancellationPending)
                {
                    e.Cancel = true;
                    break;
                }
            }

            e.Result = sb.ToString();
        }
        #endregion

        #region backgroundworker RunWorkerCompleted event
        void myWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                lblStatus.Text = "User Cancelled";
            }
            else if (e.Error != null)
            {
                txtResult.Text = e.Error.ToString();
                lblStatus.Text = "Error";
            }
            else
            { 
                string result = e.Result.ToString();
                txtResult.Text = result;
                lblStatus.Text = "Done";
            }
        }
        #endregion

        #region backgroundworker ProgressChanged event
        void myWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            lblStatus.Text = string.Format("Counting number : {0} %...", e.ProgressPercentage.ToString());
        }
        #endregion

        #region simulate heavy work
        private int PerformHeavyOperation(int i)
        {
            System.Threading.Thread.Sleep(100);
            return i * 1000;
        }
        #endregion

        #region start buton click method
        private void btnStart_Click(object sender, EventArgs e)
        {
            int numericValue = (int)this.numericUpDown.Value;
            object[] arrObjects = new object[] { numericValue };

            if (!myWorker.IsBusy)
            {
                if (!string.IsNullOrEmpty(txtResult.Text))
                    txtResult.Text = "";

                myWorker.RunWorkerAsync(arrObjects);
            }
            else
                lblStatus.Text = "Work processing";
        }
        #endregion

        #region clear click method
        private void btnClear_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Clear data?", "Confirm", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK)
                txtResult.Text = "";
        }
        #endregion

        #region cancel buton click method
        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (myWorker.IsBusy)
            { 
                myWorker.CancelAsync();
            }
            else
            {
                lblStatus.Text = "No cancel work";
            }
        }
        #endregion

1번 예제 소스 :

BackgroundWorker1.zip

 

2번 예제 소스 :

BackgroundWorker2.zip


'C#' 카테고리의 다른 글

멀티플(multiple) 윈도우 - 2  (0) 2015.05.07
데이타베이스 라이브러리  (0) 2015.04.22
텍스트 로그 파일 라이브러리 - 3  (0) 2015.02.21
텍스트 로그 파일 라이브러리 - 2  (0) 2015.02.21
멀티플(multiple) 윈도우 - 1  (0) 2015.01.24
posted by 따시쿵
2015. 2. 21. 07:43 C#

log4net 을 이용한 로그파일 쓰는 예제입니다. 라이브러리 다운로드와 자세한 설명은 다음의 사이트를 이용하시면 됩니다. http://logging.apache.org/log4net/index.html


파일 이름이 날짜로 되어서 구분하는 예제를 만들었습니다.


app.config App.config


<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  
<!--log4net 설정하는 부분 시작-->    
  <log4net>    
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
      <file value="logs\" />
      <datePattern value="yyyy-MM-dd'.log'" />
      <staticLogFileName value="false" />
      <appendToFile value="true" />
      <rollingStyle value="Date" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="50MB" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
      </layout>
    </appender>
  
    
    <root>
      <!--LogLevel: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -->
      <level value="ALL" />
      <appender-ref ref="LogFileAppender" />
    </root>
  </log4net>
<!--log4net 설정하는 부분 종료--> 
  

    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>


사용예제


            new Thread(delegate()
                {
                    for (int i = 0; i <= 100; i++)
                    {
                        Logger.WriteLog(LogLevel4N.INFO, i.ToString());
                    }
                }).Start();

            new Thread(delegate()
            {
                for (int i = 0; i <= 100; i++)
                {
                    Logger.WriteLog(LogLevel4N.DEBUG, i.ToString());
                }
            }).Start();

            new Thread(delegate()
            {
                for (int i = 0; i <= 100; i++)
                {
                    Logger.WriteLog(LogLevel4N.ERROR, i.ToString());
                }
            }).Start();

            new Thread(delegate()
            {
                for (int i = 0; i <= 100; i++)
                {
                    Logger.WriteLog(LogLevel4N.WARN, i.ToString());
                }
            }).Start();      


posted by 따시쿵
2015. 2. 21. 07:21 C#

Trace class를 이용해서 파일에 로그 파일을 쓰는 경우가 있습니다. 이런 경우에도 설정 파일(app.config)을 이용해서 파일에 쓰는 경우를 보여 줍니다.


Trace.WriteLine 을 이용한 경우입니다.

System.IO.StreamWriter class 와 로그 파일에 lock mode 를 걸지 않는 경우입니다.


app.config


  <!--Trace.WriteLine 을 설정하는 부분 시작 -->
  <system.diagnostics>
    <trace autoflush="true" indentsize="4">
      <listeners>
        <add name="myListener" type="System.Diagnostics.TextWriterTraceListener" initializedata="TextWriterOutput.log" />
        <remove name="Default" />
      </remove>
    </trace>
  </system.diagnostics>
 <!--Trace.WriteLine 을 설정하는 부분 종료 -->


LoggerSystem.cs


    #region LoggerSystem class
    public static class LoggerSystem
    {
        public static void Error(string message, string module)
        {
            WriteEntry(message, "error", module);
        }

        public static void Error(Exception ex, string module)
        {
            WriteEntry(ex.Message, "error", module);
        }

        public static void Warning(string message, string module)
        {
            WriteEntry(message, "warning", module);
        }

        public static void Info(string message, string module)
        {
            WriteEntry(message, "info", module);
        }

        private static void WriteEntry(string message, string type, string module)
        {
            Trace.WriteLine(
                    string.Format("[{0}],{1},{2},{3}",
                                  DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                  type,
                                  module,
                                  message));
        }
    }
    #endregion


사용예제


            new Thread(delegate()
                {
                    for (int i = 0; i <= 1000; i++)
                    {
                        LoggerSystem.Error("button1_Click = " + i.ToString(), "myapp");
                    }
                }).Start();

            new Thread(delegate()
            {
                for (int i = 0; i <= 1000; i++)
                {
                    LoggerSystem.Info("button2_Click = " + i.ToString(), "myapp");
                }
            }).Start();  


'C#' 카테고리의 다른 글

BackgroundWorker class  (0) 2015.03.02
텍스트 로그 파일 라이브러리 - 3  (0) 2015.02.21
멀티플(multiple) 윈도우 - 1  (0) 2015.01.24
멀티스레드 환경에서 UI 에 데이타 표시할 경우  (0) 2015.01.15
Task 클래스  (0) 2015.01.10
posted by 따시쿵
2015. 1. 24. 10:07 C#

1. 

메인 폼에서 showDialog 를 이용해서 폼 Form2 를 새로 만듭니다.

Form2 창에서 OK, Cancel 버튼을 선택하는 것을 보여 주는 예제입니다.


실행화면




프로그램


1. 메인 창

        private void btnFormTwo_Click(object sender, EventArgs e)
        {
            Form2 f2 = new Form2();
            if (f2.ShowDialog() == DialogResult.OK)
                MessageBox.Show("OK button clicked");
            else if (f2.ShowDialog() == DialogResult.Cancel)
                MessageBox.Show("Cancel button clicked");
        }


2. Form2

        private void btnOK_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
        }


2.

메인 창에서 Form2를 띄웁니다. 메인창에 있는 textbox 를 Form2 에 전달하고, Form2 에서 대문자, 소문자로 변경한 내용을 다시 메인창의 텍스트박스에서 보여지게 합니다.


실행화면






프로그램


1. 메인 창

        public static TextBox tb = new TextBox();
        private void btnChangeCase_Click(object sender, EventArgs e)
        {
            Form2 f2 = new Form2();
            if (f2.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                MessageBox.Show("OK");
            else
                MessageBox.Show("Cancel");
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            tb = txtChangeCase;
        }


2. Form2

using System.Globalization;
using System.Threading;

        private void btnOK_Click(object sender, EventArgs e)
        {
            string changeCase = MainForm.tb.Text;

            if (radioButton1.Checked)
                changeCase = changeCase.ToUpper();
            else if (radioButton2.Checked)
                changeCase = changeCase.ToLower();
            else if (radioButton3.Checked)
            {
                CultureInfo properCase = Thread.CurrentThread.CurrentCulture;
                TextInfo textInfoObject = properCase.TextInfo;

                changeCase = textInfoObject.ToTitleCase(changeCase);
            }

            MainForm.tb.Text = changeCase;

            this.DialogResult = System.Windows.Forms.DialogResult.OK;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
        }

posted by 따시쿵
2015. 1. 15. 16:59 C#

Windows Forms의 컨트롤은 특정 스레드에 바인딩되며 스레드로부터 안전하지 않습니다. 따라서 다른 스레드에서 컨트롤의 메서드를 호출할 경우 해당 컨트롤의 호출 메서드 중 하나를 사용하여 호출을 적절한 스레드에 마샬링해야 합니다. 이 속성을 사용하면 호출 메서드를 호출해야 하는지 여부를 확인할 수 있습니다. 이 방법은 컨트롤을 소유한 스레드를 알 수 없는 경우 유용합니다.


컨트롤의 핸들이 없으면 InvokeRequired는 창 핸들이 있는 컨트롤이나 폼을 찾을 때까지 해당 컨트롤의 부모 체인을 위로 검색합니다. 적절한 핸들을 찾을 수 없으면InvokeRequired 메서드는 false를 반환합니다.


즉, 동일한 스레드에서 호출이 발생하여 Invoke가 필요하지 않거나 다른 스레드에서 컨트롤이 만들어졌지만 컨트롤의 핸들은 아직 만들어지지 않은 경우 InvokeRequired는false를 반환할 수 있습니다.

컨트롤의 핸들이 아직 만들어지지 않은 경우 컨트롤에 대한 속성, 메서드 또는 이벤트를 호출해서는 안 됩니다. 이렇게 하면 배경 스레드에서 컨트롤의 핸들이 만들어져 메시지 펌프 없이 스레드에서 컨트롤이 격리되고 응용 프로그램이 불안정해질 수 있습니다.


InvokeRequired 가 배경 스레드에서 false를 반환하면 IsHandleCreated 값을 확인하여 이러한 상황을 방지할 수도 있습니다. 컨트롤 핸들이 아직 만들어지지 않은 경우 핸들이 만들어질 때까지 기다린 후 Invoke 또는 BeginInvoke를 호출해야 합니다. 일반적으로 이러한 경우는 폼이 표시되기 전이나 Application.Run이 호출되기 전의Application.Run(new MainForm())에서와 같이 응용 프로그램의 기본 폼 생성자에서 배경 스레드가 만들어지는 경우에만 발생합니다.


다음은 멀티쓰레드간에 사용할 수 있는 몇가지 예제를 보여 줍니다.


1. 컨트롤의 InvokeRequired 속성을 이용하는 경우


if (listBox1.InvokeRequired)
{
    listBox1.BeginInvoke(new MethodInvoker(delegate
    {
        listBox1.Items.Add(content);
    }));
}
else
    listBox1.Items.Add(content);

}


2. Action 과 Invoke method를 이용하는 경우


Action del = delegate()
            {
                textBox1.AppendText(s + System.Environment.NewLine);
            };
Invoke(del);


3. Invoke method 와 무명메소드를 이용하는 경우


Invoke((MethodInvoker)delegate
{
    textBox1.AppendText(s + System.Environment.NewLine);
});


4. Invoke method와 EventHanlder 를 이용하는 경우

private void Form1_Load(object sender, EventArgs e)
{
     new Thread(delegate()
         {
             this.Invoke(new EventHandler(displaytext));                    
          }).Start();
}

private void displaytext(object sender, EventArgs e)
{
    richTextBox1.Text = "메시지 출력하기";
}


'C#' 카테고리의 다른 글

텍스트 로그 파일 라이브러리 - 2  (0) 2015.02.21
멀티플(multiple) 윈도우 - 1  (0) 2015.01.24
Task 클래스  (0) 2015.01.10
텍스트 로그 파일 라이브러리 - 1  (0) 2015.01.09
ManualResetEvent 클래스  (0) 2014.12.24
posted by 따시쿵
2015. 1. 10. 18:03 C#

비동기 작업을 나타냅니다.


다음 예제에서는 TaskFactory.StartNew 메서드를 사용하여 작업을 시작하는 방법을 보여 줍니다.


출처 : http://msdn.microsoft.com/ko-kr/library/system.threading.tasks.task(v=vs.110).aspx


실행 화면


예제 프로그램

// Expected results:
// 		Task t1 (alpha) is created unstarted.
//		Task t2 (beta) is created started.
//		Task t1's (alpha) start is held until after t2 (beta) is started.
//		Both tasks t1 (alpha) and t2 (beta) are potentially executed on 
//           threads other than the main thread on multi-core machines.
//		Task t3 (gamma) is executed synchronously on the main thread.

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

            // Construct aun unstarted task
            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.ToString());

            // Wait for the task to finish
            t1.Wait();

            // Construct an unstarted task
            Task t3 = new Task(action, "gamma");

            // Run it synchronously
            t3.RunSynchronously();

            // Although the task was run synchronously. it is a good practice
            // to wait for it in the event exception were thrown by task.
            t3.Wait();

            // 프로그램 종료 방지
            Console.Read();



Task 를 만들어서 실행하는 방법들을 설명합니다.


실행 화면



예제 프로그램


        static void Main(string[] args)
        {
            // use an Action delegate and named method
            Task task1 = new Task(new Action(printMessage));

            // use an anonymous delegate
            Task task2 = new Task(delegate { printMessage(); });

            // use a lambda expressiion and a named method
            Task task3 = new Task(() => printMessage());

            // use a lambda expression and an anonymous method
            Task task4 = new Task(() => { printMessage(); });
            
            task1.Start();
            task2.Start();
            task3.Start();
            task4.Start();

            Console.WriteLine("Main method complete. Press <enter> to finish");
            Console.WriteLine("Main Thread={0}", Thread.CurrentThread.ManagedThreadId.ToString());
            Console.ReadLine();
        }

        private static void printMessage()
        {
            Console.WriteLine("Task={0}, Thread={1}",
                                    Task.CurrentId, Thread.CurrentThread.ManagedThreadId.ToString());
        }


Task<TResult> 를 보여주는 예제입니다.


실행 화면




예제 프로그램

        static void Main(string[] args)
        {
            Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);
            t.Start();
            t.Wait();

            // Get the result (the Result property internally calls Wait) 
            Console.WriteLine("The sum is: " + t.Result);   // An Int32 value
            Console.ReadLine();
        }

        private static Int32 Sum(Int32 n)
        {
            Int32 sum = 0;
            for (; n > 0; n--)
                checked { sum += n; }
            return sum;
        }

posted by 따시쿵
2015. 1. 9. 10:22 C#

윈도우/콘솔 프로그램 중 로그 파일을 남기고 싶을 경우가 종종 있습니다.


클라이언트 경우에는 서버로 데이타를 전송한 목록을 가지고 있다거나 서버에서는 클라이언트에서 전송 된 데이타를 정상적으로 받았는지 확인 해 볼 필요가 있습니다. 이런 경우 텍스트 파일로 남기는 경우가 필요한데 이런 경우에 사용하면 됩니다.


멀티 쓰레드 환경에서 작동하도록 작성했으며 라이브러리와 사용 예제를 올립니다.


실행파일 폴더를 가져와서 Log 폴더를 작성하고, 일자별로 파일을 생성하며 시간별로 로그를 쌓습니다.



LogFile.cs


LogFile.cs


using System;
using System.Data;
using System.Configuration;
using System.IO;
using System.Diagnostics;

/// 
/// Summary description for LogFile
/// 
public class LogFile
{

    private static string strLogDir = System.IO.Directory.GetCurrentDirectory() + @"\Log\";
	private static string strLogFile = "Log";
    private static readonly object thisLock = new object();

	public LogFile()
	{
	}

	public static void SetLogPath(string strDir)
	{
		strLogDir = strDir;
	}

	public static void SetLogFile(string strFile)
	{
		strLogFile = strFile;
	}

	public static void WriteLog(string strLog)
	{
		WriteLog(strLog, LogCode.Infomation, strLogFile);
	}

	public static void WriteLog(string strLog, string strFileName)
	{

		WriteLog(strLog, LogCode.Infomation, strFileName, strLogDir);
	}

	public static void WriteLog(string strLog, string strFileName, string strPath)
	{
		WriteLog(strLog, LogCode.Infomation, strFileName, strPath);
	}

	public static void WriteLog(string strLog, LogCode logCode)
	{
		WriteLog(strLog, logCode, strLogFile);
	}

	public static void WriteLog(string strLog, LogCode logCode, string strFileName)
	{

		WriteLog(strLog, logCode, strFileName, strLogDir);
	}

	public static void WriteLog(string strLog, LogCode logCode, string strFileName, string strPath)
	{
		string strFullName;

		if (!Directory.Exists(strPath))
		{
			Directory.CreateDirectory(strPath);
		}

		if (strPath.EndsWith(@"\") == false || strPath.EndsWith("/") == false)
		{
			strPath = strPath + @"\";
		}
		strFullName = strPath + strFileName + "_" + DateTime.Now.ToShortDateString() + ".txt";

		string strFullLog = DateTime.Now.ToString("HH:mm:ss") + " (" + logCode.ToString() + ")" + " : " + strLog;

        lock(thisLock)
        { 
		    StreamWriter sw = new StreamWriter(strFullName, true, System.Text.Encoding.UTF8, 4096);
		    sw.WriteLine(strFullLog);
		    sw.Close();
        }
	}

	public enum LogCode
	{
		Infomation = 0,
		Success = 1,
		Error = -1,
		Failure = -2,
		Warning = -10,
		SystemError = -101,
		ApplicationError = -201
	}
}


사용예제


            new Thread(delegate()
                {                    
                    for (int i = 0; i <= 100; i++)
                        LogFile.WriteLog(string.Format("Thread[1] = {0}", i.ToString()));

                }).Start();

            new Thread(delegate()
                {
                    for (int i = 0; i <= 100; i++)
                        LogFile.WriteLog(string.Format("Thread[2] = {0}", i.ToString()));

                }).Start();;


'C#' 카테고리의 다른 글

텍스트 로그 파일 라이브러리 - 2  (0) 2015.02.21
멀티플(multiple) 윈도우 - 1  (0) 2015.01.24
멀티스레드 환경에서 UI 에 데이타 표시할 경우  (0) 2015.01.15
Task 클래스  (0) 2015.01.10
ManualResetEvent 클래스  (0) 2014.12.24
posted by 따시쿵
2014. 12. 24. 11:42 C#

하나 이상의 대기 중인 스레드에 이벤트가 발생했음을 알립니다. 이 클래스는 상속될 수 없습니다.


ManualResetEvent 를 사용하여 스레드는 신호를 보냄으로써 서로 통신할 수 있습니다. 일반적으로 이 통신은 다른 스레드가 처리되기 위해 먼저 하나의 스레드가 완료해야 하는 작업과 관련이 있습니다.


하나의 스레드에서 다른 스레드의 처리를 위해 먼저 완료되어야 하는 작업을 시작할 때 Reset을 호출하여 ManualResetEvent를 신호 없음 상태로 설정합니다. 이 스레드는 ManualResetEvent를 제어하는 것으로 간주될 수 있습니다. ManualResetEvent 에 대해 WaitOne을 호출하는 스레드는 차단되며 신호를 기다립니다. 제어 스레드는 해당 작업을 끝나면 Set을 호출하여 대기 중인 스레드가 계속될 수 있음을 알립니다. 대기 중인 모든 스레드는 해제됩니다.


출처 : http://msdn.microsoft.com/ko-kr/library/system.threading.manualresetevent(v=vs.110).aspx



실행 화면



예제 프로그램

       // mre is used to block and relrease threads manually. It is 
        // created in unsignaled state.
        private static ManualResetEvent mre = new ManualResetEvent(false);

        static void Main(string[] args)
        {
            Console.WriteLine("\nStart 3 named threads that block on a ManualResetEvent\n");

            for (int i = 0; i <= 2; i++)
            {
                Thread t = new Thread(ThreadProc);
                t.Name = "Thread_" + i.ToString();
                t.Start();
            }

            #region 테스트1 - Set()
            Thread.Sleep(500);
            Console.WriteLine("\nWhen all three threads have started, press Enter to call Set()\n" +
                              "\nto release all the threads.\n");
            Console.ReadLine();

            mre.Set();

            #endregion

            #region 테스트2 - Reset()
            Thread.Sleep(500);
            Console.WriteLine("\nWhen a ManualResetEvent is signaled, threads that call WaitOne()" +
                              "\ndo not block. Press Enter to show this.\n");
            Console.ReadLine();

            for (int i = 3; i <= 4; i++)
            {
                Thread t = new Thread(ThreadProc);
                t.Name = "Thread_" + i.ToString();
                t.Start();

            }
            Thread.Sleep(500);
            Console.WriteLine("\nPress Enter to call Reset(), so that threads once again block\n" +
                              "\nwhen they call WaitOne\n");
            Console.ReadLine();

            mre.Reset();

            #endregion

            #region 테스트3 - Set()
            //Start a thread that waits on the ManualResetEvent
            Thread t5 = new Thread(ThreadProc);
            t5.Name = "Thread_5";
            t5.Start();

            Thread.Sleep(500);
            Console.WriteLine("\nPress Enter to call Set() and conclude the demo\n");
            Console.ReadLine();

            mre.Set();

            #endregion

            Console.ReadLine();
        }

        private static void ThreadProc()
        {
            string name = Thread.CurrentThread.Name;

            Console.WriteLine(name + " starts and call mre.WaitOne()");

            mre.WaitOne();

            Console.WriteLine(name + " ends");
        }


posted by 따시쿵
prev 1 2 next