c# System.Timers.Timer로 비주얼 컨트롤 제어하기

멀티뜨레드로 인한 크로스-뜨레드 예외 발생

메인 뜨레드로부터 분리된 뜨레드에서 비주얼 컨트롤을 제어하려 하면 원칙적으로 크로스-뜨레드 오류가 발생한다. 이러한 오류는 디버그 빌드에서는 예외로 처리되지만 릴리스 빌드에서는 그냥 오류가 생긴 대로 출력하고 넘어간다. 릴리스 모드에서 예외로 처리가 되지 않는다고 괜찮은 게 아니라 오류를 무시하는 것이므로 엉뚱한 결과가 나타날 수 있다. 따라서 디버그 빌드에서 분명하게 조치를 취해야 한다.

멀티뜨레드 타이머 System.Timers.Timer

System.Windows.Forms.Timer는 싱글 뜨레드로 작동하고 System.Timers.Timer는 멀티뜨레드로 작동한다. 그런데 후자의 타이머가 일반적인 멀티뜨레드의 경우와는 다르게 작동하여 주의를 해야 한다.

아래의 예제는 디버그 빌드에서 작동하면 안 되어야 하지만 된다.

System.Timers.Timer Timer1 = new();

private void Form1_Load(object sender, EventArgs e)
{
    Timer1.Elapsed += Timer1_Elapsed;
    Timer1.Interval = 1000;
    Timer1.Enabled = true;
}

private void Timer1_Elapsed(object? sender, ElapsedEventArgs e)
{
    Method1(null);
}

void Method1(object object1)
{
    label1.Text = "a";
}

그러나 아래와 같이 제어하는 대상을 CheckBox로 바꾸면 안 된다. 그런데 크로스-뜨레드 예외로 처리하지도 않아서 아무 일도 일어나지 않는다. 모르고 지나칠 수 있으므로 주의하는 게 좋다.

void Method1(object object1)
{
    checkBox1.Checked = true;
}

제대로 작동하게 하려면 아래와 같이 Invoke를 해야 한다.

private void Timer1_Elapsed(object? sender, ElapsedEventArgs e)
{
    checkBox1.Invoke(checkBoxInvoke);

    void checkBoxInvoke()
    {
        checkBox1.Checked = true;
    }
}