[(주)북스 | 이노소프트]/SW개발정보

C# WinForms 설비 통신 중 화면 멈춤 방지: async·await와 취소 처리

BOOX 2026. 10. 17. 19:29

설비 제어 프로그램에서 PLC나 장치 응답을 기다리는 동안 버튼과 화면이 멈춰 보인다면, 통신 작업이 UI 스레드를 점유하는지 먼저 확인해 보세요. 단순히 작업을 백그라운드로 옮기는 것보다, 통신 라이브러리가 비동기 API를 제공하는지와 취소·시간 초과를 지원하는지를 함께 살피는 편이 안전합니다.

이 예제는 WinForms 화면에서 비동기 흐름을 익히기 위한 시뮬레이션입니다. 실제 PLC 주소, 출력 신호, 모션 명령은 포함하지 않습니다. 현장 적용 전에는 장치 매뉴얼, 통신 시간 초과, 인터록과 안전 절차를 별도로 검증해야 합니다.

왜 화면이 멈출까요?

WinForms는 기본적으로 UI 스레드에서 이벤트와 화면 갱신을 처리합니다. 버튼 이벤트 안에서 Thread.Sleep, 오래 걸리는 동기 통신, Task.Wait() 또는 .Result를 사용하면 그 스레드가 기다리는 동안 입력과 다시 그리기가 지연될 수 있습니다.

비동기 메서드는 Task 또는 Task<T>를 반환하고 호출부에서 await합니다. await는 결과를 기다리는 동안 호출 스레드를 계속 점유하지 않게 해 UI가 다른 이벤트를 처리할 기회를 줍니다. UI 이벤트 핸들러는 프레임워크 시그니처 때문에 async void가 필요할 수 있지만, 그 안에서 호출하는 일반 메서드는 Task를 반환하도록 만드세요.

 

WinForms 예제: 응답 대기, 시간 초과, 취소

아래 코드는 실제 장치 통신 대신 취소 가능한 0.5초 대기로 흐름을 보여줍니다. btnCancel은 취소 버튼, lblStatus는 상태 표시 레이블이라고 가정합니다. C# 8 이상 프로젝트에서 사용할 수 있습니다.

private CancellationTokenSource? _readCts;
private async void btnRead_Click(object? sender, EventArgs e)
{
    if (_readCts is not null) return; // 중복 요청 방지

    using var cts = new CancellationTokenSource();
    _readCts = cts;
    cts.CancelAfter(TimeSpan.FromSeconds(3)); // 예시 시간 제한
    btnRead.Enabled = false;

    try
    {
        lblStatus.Text = "통신 중...";
        string response = await ReadMockAsync(cts.Token);
        lblStatus.Text = response;
    }
    catch (OperationCanceledException)
    {
        lblStatus.Text = "취소 또는 시간 초과";
    }
    catch (Exception ex)
    {
        lblStatus.Text = $"통신 오류: {ex.Message}";
    }
    finally
    {
        _readCts = null;
        btnRead.Enabled = true;
    }
}

private static async Task<string> ReadMockAsync(CancellationToken token)
{
    await Task.Delay(500, token); // 실제 장치 읽기가 아닌 교육용 대기
    return "샘플 응답";
}

private void btnCancel_Click(object? sender, EventArgs e)
{
    _readCts?.Cancel();
}

실제 통신 API에 바꿔 넣을 때

1) 라이브러리에 ReadAsync(..., CancellationToken) 같은 비동기 API가 있으면 직접 await하고, 지원되는 경우 토큰을 전달합니다. 이미 비동기 I/O인 호출을 습관적으로 Task.Run으로 감쌀 필요는 없습니다.

2) 장치 라이브러리가 동기식이고 호출이 오래 걸리면, 제조사 권장 방식과 연결 객체의 스레드 안전성을 확인한 뒤 제한적으로 Task.Run을 검토합니다. Task.Run에 토큰만 전달해도 이미 실행 중인 임의의 동기 통신이 강제로 중단되는 것은 아닙니다. 라이브러리 자체의 응답 시간 초과나 중단 기능을 함께 설정하세요.

3) 같은 PLC 연결에 여러 읽기·쓰기를 동시에 보내도 되는지 확인합니다. 장치나 라이브러리가 동시 호출을 보장하지 않으면 요청을 순서대로 처리하고, Form 종료 때 진행 중인 작업을 취소하거나 안전하게 정리합니다.

4) 비동기 작업 도중 예외를 잡고, 성공·실패·취소 상태를 구분해 화면에 보여주세요. UI 스레드 밖에서 컨트롤을 직접 바꾸지 말고, 진행 상태는 IProgress<T>나 WinForms의 Invoke/InvokeAsync 등 현재 프레임워크에 맞는 방법으로 전달합니다.

 

현장 적용 체크리스트

□ UI 이벤트에서 .Wait(), .Result, Thread.Sleep을 제거했는가

□ 통신 라이브러리의 비동기·취소·시간 초과 동작을 확인했는가

□ 중복 요청과 Form 종료 시 정리 정책이 있는가

□ 실제 장치 적용 전 읽기 전용 시험과 안전 인터록 검증을 했는가

 

핵심은 모든 작업에 Task.Run을 붙이는 것이 아닙니다. 가능한 경우 진짜 비동기 API를 await하고, 동기식 장치 호출은 문서화된 제한 시간과 취소 방식을 확인해 UI 스레드와 분리하는 것입니다. 이 예제는 교육용이므로 실제 설비 제어에 그대로 연결하지 마세요.

 

참고 자료

Microsoft Learn, Task Asynchronous Programming (TAP) model: https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/task-asynchronous-programming-model

 

The Task Asynchronous Programming (TAP) model with async and await" - C#

Learn when and how to use Task-based async programming, a simplified approach to asynchronous programming in C#.

learn.microsoft.com

Microsoft Learn, Cancel a list of tasks: https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/cancel-an-async-task-or-a-list-of-tasks

 

Cancel a list of tasks - C#

Learn how to use cancellation tokens to signal a cancellation request to a list of tasks.

learn.microsoft.com

Microsoft Learn, Windows Forms events: https://learn.microsoft.com/en-us/dotnet/desktop/winforms/forms/events

 

Events Overview - Windows Forms

A brief overview about events with .NET Windows Forms.

learn.microsoft.com

 

이미지 출처: Joonspoon, “Programmer writing code with Unit Tests” (2014), Wikimedia Commons, CC BY-SA 4.0. 사진은 C# 또는 WinForms 화면이 아닌 일반 프로그래밍 참고 이미지입니다. 원본 및 라이선스: https://commons.wikimedia.org/wiki/File:Programmer_writing_code_with_Unit_Tests.jpg · https://creativecommons.org/licenses/by-sa/4.0/ .

 

C# 설비제어 프로그램 교육이나 장치 통신 구조를 설계할 때는 프로젝트의 .NET 버전과 사용 중인 장비 라이브러리를 먼저 확인하세요. 이노소프트의 소프트웨어 개발 및 교육 분야는 www.innosoft.kr  에서 확인하실 수 있습니다.