/*
 * From BackgroundWorker 매카니즘
 */

1. 서버로 data 송신시 -> SendWorker
2. 서버에서 data 수신시 -> RecvWorker
3. Queue에 데이타 입력시 -> SendQueue
4. Queue에 데이타 출력시 -> RecvQueue
5. 출력되어진 데이타를 Grid에 Display시 -> RecvQueue

From BackgroundWorker, 업무를 처리하는 동안, 어떤 방해도 받지 않는다.

/*
* From Process To Process, Message Send,Recv
*/

namespace RecvPackage
{
    public class Program : Form
    {
        public const int WM_COPYDATA=0x004A;

        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int dbData;
            public IntPtr lpData;
        }

        public Program()
        {
            //From FindWindow(), This Application is Detected!!
            //From FindWindow(), This Application is Detected!! //The KeyWord is Below String,,,,,
            this.Text = "RecvSendDataMonitoring";
        }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            try
            {
                switch(m.Msg)
                {
                    case WM_COPYDATA :
                    COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
                    byte[] recvData = new byte[cds.cbData];
                    Marshal.Copy(cds.lpData, recvData, 0, cds.cbData);
                    Console.WriteLine(Encoding.Default.GetString(recvData));

                    break;
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Program());
        }
    }//end of class
}//end of namespace

            

/*
BackgroundWorker를 통해 조금 더 안전하게 이벤트 기반으로 비동기 처리를 진행하는 패턴 사용해보기 (RunWorkerAsync, IsBusy)

BackgroundWorker를 통해 조금 더 안전하게 이벤트 기반으로 비동기 처리를 진행하는 패턴 사용해보기 (RunWorkerAsync, IsBusy)

BackgroundWorker를 통해 조금 더 안전하게 이벤트 기반으로 비동기 처리를 진행하는 패턴 사용해보기 (RunWorkerAsync, IsBusy)

BackgroundWorker를 통해 조금 더 안전하게 이벤트 기반으로 비동기 처리를 진행하는 패턴 사용해보기 (RunWorkerAsync, IsBusy)
*/

1. ".." 은 현재 실행되는 모습이다. 예를 들어 마우스를 움직인다던지, 키보드를 사용한다던지, 어떤 행위를 하는
2. 메세지는 백그라운드로 실행되는 행위의 모습이다. 예을 들어 서버와의 통신, 프로그래스바 등이 움직이는
행위를 연출할수 있다.
클라이언트와 서버와의 통신시에 자유롭게 마우스나 키보드나 행위를 할수 있어야 한다.
프로그래스바가 움직이는동안에서 마우스나 키보드나 행위를 할수 있어야 한다.
이런모습을 100에서 9999까지의 숫자중에 프라임넘버가 몇개인지 COUNT하는 TASK를 텍스트로 표현해보았다.
Console.WriteLine(">>>>>>Long running task start!!");
Console.WriteLine(">>>>>>Prime Number Cnt:[" + cnt.ToString("0000") + "]");
Console.WriteLine(">>>>>>Long running task end!!");
Console.WriteLine(">>>>>>Long running task completed!!");

3. 실제소스코드이다. 위를 표현한,ㅡㅡㅡㅡㅡ

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
 
namespace TrisPackage.Tris
{
    class Program
    {
        static void Main(string[] args)
        {
            BackgroundWorkerCls bwt = new BackgroundWorkerCls();
 
            while(true)
            {
                bwt.Execute();
            }
        }
    }
 
    class BackgroundWorkerCls
    {
        private BackgroundWorker worker;
 
        public BackgroundWorkerCls()
        {
            worker = new BackgroundWorker();
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        }
        ~BackgroundWorkerCls()
        {
            worker.DoWork -= new DoWorkEventHandler(worker_DoWork);
        }
 
        public void Execute()
        {
            Console.Write("..");
 
            // InvalidOperationException Protection!!
            // InvalidOperationException Protection!!
            if(!worker.IsBusy) worker.RunWorkerAsync();
        }
 
        //Work Thread Execute Task Method
        //Work Thread Execute Task Method
        //Work Thread Execute Task Method
        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            Console.WriteLine("");
            Console.WriteLine(">>>>>>Long running task start!!");

            int ii,kk,ff,prime,cnt=0;

            for(ii=100; ii < 9999; ii++)
            {
                prime = ii;
                ff = 0;
                for(kk=1; kk <= prime; kk++)
                {
                        if(prime / kk * kk == prime) ff++;
                }

                if(ff == 2) cnt++;
             }
             Console.WriteLine("");
             Console.WriteLine(">>>>>>Prime Number Cnt:[" + cnt.ToString("0000") + "]");
             Console.WriteLine("");
             Console.WriteLine(">>>>>>Long running task end!!");
             Console.WriteLine("");
        }

        //Work Thread Execute Task Method
        //Work Thread Execute Task Method
        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
                Console.WriteLine("");
                Console.WriteLine(">>>>>>Long running task completed!!");
                Console.WriteLine("");
        }
    }
}

 

결론적으로 위의 이미지에서 보이는 .....은 평상시에 우리가 화면을 핸들링하는 모습이고, 나머지의 메세지는 백그라운드를 통해서 이루어지는, 즉 비동기적으로 안보이는 작업들이 행해지는 모습을 나타낸것입니다.

C# 개요(Introduction)

C#은 C++의 컴퓨팅 파워와(1) 비주얼 베이직의 편리함(2)을 하나로 합치기 위해 마이크로소프트사(MS)에서 개발한 새로운 객체 지향 프로그래밍 언어입니다.

C#은 C++의 컴퓨팅 파워와 비주얼 베이직의 편리함을 하나로 합치기 위해 마이크로소프트사(MS)에서 개발한 새로운 객체 지향 프로그래밍 언어입니다.

C#은 C++의 컴퓨팅 파워와 비주얼 베이직의 편리함을 하나로 합치기 위해 마이크로소프트사(MS)에서 개발한 새로운 객체 지향 프로그래밍 언어입니다.

C#은 C++의 컴퓨팅 파워와 비주얼 베이직의 편리함을 하나로 합치기 위해 마이크로소프트사(MS)에서 개발한 새로운 객체 지향 프로그래밍 언어입니다.

C#은 C++의 컴퓨팅 파워와 비주얼 베이직의 편리함을 하나로 합치기 위해 마이크로소프트사(MS)에서 개발한 새로운 객체 지향 프로그래밍 언어입니다.

/*
C# 언어 대리자 개념은 최고 수준의 언어 지원 및 해당 개념 관련 형식 안정성을 제공합니다.
함수 포인터는 호출 규칙을 더욱 세부적으로 제어해야 하는 유사한 시나리오용으로 C# 9에 추가되었습니다. 
대리자와 연결된 코드는 대리자 형식에 추가된 가상 메서드를 사용하여 호출됩니다.
*/

/*----------------------------------------------------------------------------------
>>대리자

1.  ElapsedEventHandler 대리자
1.1 public delegate void ElapsedEventHandler(object sender, ElapsedEventArgs e);

>>대리자 호출

1.  Timer.Elapsed 이벤트
1.1 public event System.Timers.ElapsedEventHandler Elapsed;
----------------------------------------------------------------------------------*/


c# 객체지향 언어이긴 하지만 함수지향형 언어가 갖는 특징을 갖기도 합니다.
이를테면 c언어의 함수 포인터에 해당하는 기능이 c#에도 있다는 겁니다.
오히려, c언어의 함수포인터보다 기능이 더 강화되었습니다.

1. 대리자(Delegate)

c# 초기 버젼부터 있던 기능입니다. c언어의 함수포인터를 그대로 차용한거나 다름없습니다.
메소드의 위치를 간직하고 있으면서, 그 메서드를 실행해 주는 역할을 합니다.

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

namespace TEST
{
class Program
{
delegate void DelegateMethod(int a);

static void method1(int a){Console.WriteLine("method1 called!! a = {0}", ++a);}
static void method2(int a){Console.WriteLine("method2 called!! a = {0}", ++a);}
static void method3(int a){Console.WriteLine("method3 called!! a = {0}", ++a);}
static void method4(int a){Console.WriteLine("method4 called!! a = {0}", ++a);}
static void method5(int a){Console.WriteLine("method5 called!! a = {0}", ++a);}
static void method6(int a){Console.WriteLine("method6 called!! a = {0}", ++a);}
static void method7(int a){Console.WriteLine("method7 called!! a = {0}", ++a);}
static void method8(int a){Console.WriteLine("method8 called!! a = {0}", ++a);}
static void method9(int a){Console.WriteLine("method9 called!! a = {0}", ++a);}

static void Main()
{
DelegateMethod method = null;

method += method1;
method += method2;
method += method3;
method += method4;
method += method5;
method += method6;
method += method7;
method += method8;
method += method9;

method(0);
}
}
}


결과) 동시에 실행이 된다고 볼수 있다. a의 값을 주목

D:\tmp\console>sample.exe
method1 called!! a = 1
method2 called!! a = 1
method3 called!! a = 1
method4 called!! a = 1
method5 called!! a = 1
method6 called!! a = 1
method7 called!! a = 1
method8 called!! a = 1
method9 called!! a = 1
D:\tmp\console>

/*Handler
- DoWorkEventHandler
- RunWorkerCompletedEventHandler
*/
using System.ComponentModel

 

System.ComponentModel 네임스페이스

구성 요소와 컨트롤의 런타임 및 디자인 타임 동작을 구현하는 데 사용되는 클래스를 제공합니다. Provides classes that are used to implement the run-time and design-time behavior of components and controls. 이 네임스

docs.microsoft.com

class TrisCls
{
     int xpos,ypos;
     BackgroundWorker sendWork;

    public void running()
    {
        ConsoleKeyInfo keyinfo;

        init();
        while(true)
        {
            //add
        }
    }
    void init()
    {
        xpos=ypos=0;
       
        sendWorker = new BackgroundWorker();
        sendWorker.DoWork += new DoWorkEventHandler(sendWorker_DoWork);
        sendWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(sendWorker_RunWorkerCompleted);
    }
    void DoWorkEventHandler(object sender, DoWorkEventArgs e)
    {
         Console.WriteLine("DoWorkEventHandler>>" + xpos.ToString("0000") );
         xpos++;
    }
    void sendWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("sendWorker_RunWorkerCompleted>>" + ypos.ToString("0000") );
        ypos++;
    }
}

int exchange_check()
{
int ii,kk,ff,tmp;
int[,] tristmp = new int[MAPY,MAPX];
int[,] designtmp = new int[ARR,ARR];

for(ii=0; ii<MAPY; ii++)
for(kk=0; kk<MAPX; kk++)
{
tristmp[ii,kk]=tris[ii,kk];
}

for(ii=0; ii<ARR; ii++)
for(kk=0; kk<ARR; kk++)
{
designtmp[ii,kk]=design[ii,kk];
}

for(ii=0; ii<ARR; ii++)
for(kk=0; kk<ARR; kk++)
{
if(ypos+ii>MAPY-1) continue;
if(xpos+kk>MAPX-1) continue;
if(xpos+kk<0) continue;

if(designtmp[ii,kk]==1) tristmp[ypos+ii,xpos+kk]=0;
}

//exchange//exchange//exchange//exchange//exchange
//exchange//exchange//exchange//exchange//exchange
//exchange//exchange//exchange//exchange//exchange
//exchange//exchange//exchange//exchange//exchange

/*
{0,0},{0,1},{0,2},{0,3},
{1,0},{1,1},{1,2},{1,3},
{2,0},{2,1},{2,2},{2,3},
{3,0},{3,1},{3,2},{3,3},
*/

for(ii=0; ii<3; ii++)
{
//add
}
tmp=designtmp[1,1];
designtmp[1,1]=designtmp[1,2];
designtmp[1,2]=designtmp[2,2];
designtmp[2,2]=designtmp[2,1];
designtmp[2,1]=tmp;

for(ii=0; ii<ARR; ii++)
for(kk=0; kk<ARR; kk++)
{
if(ypos+ii>MAPY-1) continue;
if(xpos+kk>MAPX-1) continue;
if(xpos+kk<0) continue;

if(designtmp[ii,kk]==1) tristmp[ypos+ii,xpos+kk] += 1;
}

ff=0;
for(ii=0; ii<ARR; ii++)
for(kk=0; kk<ARR; kk++)
{
if(ypos+ii>MAPY-1) continue;
if(xpos+kk>MAPX-1) continue;
if(xpos+kk<0) continue;

if(tristmp[ypos+ii,xpos+kk] > 1) ff++;
}

if(ff > 0)
{
return(FAIL);
}
else
{
for(ii=0; ii<MAPY; ii++)
for(kk=0; kk<MAPX; kk++)
{
tris[ii,kk]=tristmp[ii,kk];
}

for(ii=0; ii<ARR; ii++)
for(kk=0; kk<ARR; kk++)
{
design[ii,kk]=designtmp[ii,kk];
}
}
return(SUCC);
}

/*TrisPackage.Tris/draw();*/

void draw()
{
    string formattext="";
    string succsign="{}";
    string failsign="..";
    int ii,kk,ff=0;

    now=DateTime.Now;
    ____draw(0,ref ff, "Time:[" + now.ToString("yyyy-MM-dd HH:mm:ss") + "]");
    for(ii=0; ii<MAPY-1; ii++)
    {
        for(kk=1; kk<MAPX-1; kk++)
        {
            if(tris[ ii,kk] == 1) formattext=formattext+succsign;
            else formattext=formattext+failsign;
        }
        ____draw(0,ref ff,formattext);
    }
    ____draw(0,ref ff,"Score:[" + score.ToString("00000000") + "]");
}
void ____draw(int x,ref int y, string str)
{
    try
    {
        Console.SetCursorPosition(x,y);
        y++;
        Console.Write(str);
    }
    catch(ArgumentOutOfRangeException e)
    {
        Console.WriteLine(e.Message);
    }
}
    
    

+ Recent posts