C# 프로그래밍 기초 실습 전자책
시리얼포트 비동기 처리

시리얼포트 통신을 통해 데이타를 처리하기 위해서는 동기적인 방식보다 비동기적인 방식이 효율적인 경우가 대부분이다. 즉 시리얼포트 읽기나 쓰기를 별도의 작업쓰레드에서 실행하게 하여 메인쓰레드가 주변기기 통신에 묶여 있지 않게 하는 것이다.

시리얼포트에서 비동기적으로 데이타를 읽기 위해서 간단하게 사용하는 방법의 하나로 DataReceived 이벤트 핸들러를 사용하는 방법이 있다. 즉, 데이타가 시리얼포트에 도착했을 때, DataReceived 이벤트핸들러에 지정된 코드가 실행되게 된다. 아래 예제는 DataReceived 이벤트핸들러를 사용하여 COM5 포트로부터 데이타가 도착하면 이를 콘솔에 출력해 주는 간단한 샘플이다.


예제

using System;
using System.IO.Ports;

namespace SerialDataRec
{
    class Program
    {
        static void Main(string[] args)
        {
            // COM5 포트 사용
            SerialPort sp = new SerialPort("COM5");

            // DataReceived 이벤트 핸들러 지정
            // 시리얼포트에 데이타가 도착하면 실행
            sp.DataReceived += (sender, e) =>
            {
                SerialPort port = (SerialPort)sender;
                // 현재까지 도착한 데이타 모두 읽기
                string data = port.ReadExisting();

                Console.WriteLine(data);
            };

            // 시리얼 포트 열기
            sp.Open();

            // Enter 누를 때까지 프로그램 계속 실행
            Console.WriteLine("Press Enter to quit");
            Console.ReadLine();

            // 시리얼 포트 닫기
            sp.Close();
        }
    }
}




시리얼포트 작업쓰레드 활용

시리얼포트 통신에서 이벤트 핸들러를 사용하지 않고 직접 작업쓰레드를 생성해서 처리할 수도 있다. 아래 예제는 간단한 콘솔 채팅 프로그램으로 한편으로 시리얼포트 읽기를 위한 작업쓰레드를 생성하여 계속 루프를 돌며 읽기 작업을 처리하고, 다른 한편으로 메인쓰레드에서 시리얼포트에 데이타를 쓰는 작업을 할 수 있게 한 것이다. (주: 이 예제는 MSDN에서 제공하는 코드를 간결하게 Refactoring 함과 동시에 약간의 버그를 수정한 것이다)

예제

using System;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;

namespace SerialChat
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Usage: SerialChat {portName}");
                Console.WriteLine("   Ex: C> SerialChat COM3");
                return;
            }
            string portName = args[0];

            // 시리얼포트 열기
            SerialPort sp = new SerialPort(portName); 
            sp.Open();

            // 읽기 작업쓰레드: Read from serial port
            var cancel = new CancellationTokenSource();
            var readTask = Task.Factory.StartNew(() => 
            {
                while (!cancel.IsCancellationRequested)
                {
                    string readMsg = sp.ReadLine();
                    if (readMsg.ToLower() == "quit")
                    {
                        Environment.Exit(0);
                    }
                    Console.WriteLine(readMsg);
                }
            }, cancel.Token);

            // 메인쓰레드: Write to serial port
            while (true)
            {
                string sendMsg = Console.ReadLine();
                if (sendMsg.ToLower() == "quit")
                {
                    sp.WriteLine(sendMsg);
                    cancel.Cancel();                                        
                    break;
                }

                sp.WriteLine(sendMsg);
            }

            // 시리얼포트 닫기
            sp.Close();
        }
    }
}




본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.




Comment koengis@*** 8/7/2018 1:32:49 AM
Comment koengis@*** 8/7/2018 2:45:08 AM

Comment 의견/코멘트 쓰기
이메일
 *정확한 이메일이 아닐 경우 삭제될 수 있습니다
의견/코멘트
좌측의 3자리 문자들을 입력해 주십시오





아티클 모바일 링크
C# 스터디 소셜미디어
쉽게 배우는 파이썬 기초