시리얼 통신에서의 async await 사용 - C#

Software/C#|2023. 3. 28. 13:39
반응형

장비제어 프로그램의 기본은 통신입니다. 

연결된 디바이스에 따라 통신 인터페이스도 다양합니다. 그중에서도 통신의 가장 기본은 RS232 시리얼 통신 입니다. 

일반적으로 시리얼 통신은 속도도 느리고 많은 데이타를 처리하는 방식은 아니지만 경우에 따라서는 꽤 큰 데이타도 주고 받을 때가 있습니다. 작은 데이타라면 굳이 비동기 방식을 사용하지 않아도 되겠지만 큰 용량의 데이타를 처리할 때는 비동기 방식을 사용해야 할 필요도 있어서 테스트 삼아 한번 구현해 보았습니다. 

 

비동기 프로그래밍을 인터넷에 찾아 보면 대부분 웹 상에서 데이타를 받을때를 많이 설명합니다. 

제 블로그는 아무래도 장비제어를 위주로 설명을 하니 시리얼 통신을 예로 코드를 작성하였습니다. 

 

1. 외부 연결 디바이스 클래스 : 이 코드는 가상의 디바이스를 예를 들어 코딩한 것입니다. 

public class Devices
{
    private System.IO.Ports.SerialPort commPort ;

    public Devices(System.IO.Ports.SerialPort commPort)
    {
        this.commPort = commPort;
    }
    //-------------------------------------------------------------
    public int readData(ref char[] data)    // 디바이스의 데이타를 불러오기 위한 메서드 입니다. 
    {
        commPort.Write("Send your Data.");  // 데이타 송신 요청(이건 디바이스 마다 틀립니다.) 
        Thread.Sleep(5000);                 // 수신 대기 (모든 데이타가 수신될 때까지 대기)
        var receiveCount = commPort.Read(data, 0, data.Length);  // 수신된 데이타를 버퍼로 이동 

        return receiveCount;
    }
}

위의 ReadData 함수에서 Thread.Sleep(5000) 을 한 이유는 데이타 양이 많아서 모든 데이타가 수신될때 까지 오래 기다려야 하는 상황을 만들었습니다. 

 

2. MainForm

   * Main 화면에 Button 하나와 Label 하나를 올려 놓습니다. 

   * Main Form의 Load 이벤트를 구현합니다. 

   * Button 의 click 이벤트를 구현합니다. 

   * 구현된 Main 클래스 

public partial class frmMain : Form
{
    System.IO.Ports.SerialPort Comm5 = new System.IO.Ports.SerialPort();
    Devices device = new Devices(Comm5);

    public frmMain()
    {
        InitializeComponent();
    }

    private void frmMain_Load(object sender, EventArgs e)
    {
        // 통신 시리얼 포트 정의 
        Comm5.PortName = "COM5";
        Comm5.BaudRate = 9600;
        Comm5.Parity = System.IO.Ports.Parity.None;
        Comm5.StopBits = System.IO.Ports.StopBits.One;

        Comm5.Open();
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        // 버튼을 클릭하면 디바이스에서 데이타를 수신합니다. 
        char[] data = new char[20];
        label1.Text = (await Task.Run(() => device.readData(ref data))).ToString();
    }
}

* private async void button1_Click(object sender, EventArgs e)   : 버튼 클릭 이벤트에 async 를 붙여 줍니다. 

* Task.Run 을 이용하여 await 를 붙여서 데이타 수신함수를 호출 합니다. 

 

* 비동기 방식을 사용하지 않으면 Thread.Sleep(5000)  이 발생되는 동안 UI 가 멈추게 됩니다. 

* 하지만 위와 같이 비동기 방식을 사용하면 UI 가 멈추지 않고 계속 동작이 되고 수신된 데이타가 다 들어 오면 결과가 Label에 출력이 됩니다. 

반응형

댓글()