[c#] 크로스-스레드인데 예외로 처리되지 않는 경우

비주얼 객체는 메인 스레드에서 만들어진다. 메인 스레드 아닌 스레드에서 비주얼 객체를 읽는 건 괜찮은데 쓰려고 하면 제대로 되지 않을 수 있다. 되고 안 되고는 운에 달려 있기 때문에 원칙적으로 저런 시도는 크로스-스레드 예외로 처리된다. 그러나 이러한 모든 시도들이 예외로 처리되는 건 아니라서 주의하는 게 좋다.

아래의 코드는 메인 스레드 아닌 스레드에서 DataGridView의 행을 바꾸는 예제다. 전형적인 크로스-스레드이지만 잘 작동한다. DataGridView는 스레드-세이프하지 않기 때문에 메인 스레드 아닌 스레드에서 행을 추가하거나 삭제하면 크로스-스레드 예외로 처리된다. 헌데 이유는 알 수 없지만 행을 바꾸는 작업은 허용한다.

class Class1
{
    public int Int { get; set; }
}

BindingList<Class1> Class1s = new();

private void Form1_Load(object sender, EventArgs e)
{
    Class1 class1 = new();

    class1.Int = 1;

    Class1s.Add(class1);

    dataGridView1.DataSource = Class1s;
}

private void button1_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(task, 2);

    void task(object? object1)
    {
        Class1 class1 = new();

        class1.Int = (int)object1!;

        Class1s[0] = class1;
    }
}

잘 되니까 행을 바꿀 때 invoke를 쓰지 않는 건 나쁜 방법이다. 되든 안 되든 메인 스레드 아닌 스레드에서 비주얼 객체의 내용을 바꿀 때에는 invoke를 통하는 게 좋다. 예외로 처리되지 않는다는 게 늘 정상으로 작동한다는 보장은 아니기 때문이다. 크로스-스레드 상황에는 애플리케이션이 예외 처리 메시지를 내지 않고 그냥 종료되기도 한다. 이러면 영문을 알 수 없어서 문제를 찾아 해결하는 데에 고생을 하게 된다. 바꿔 말하면 애플리케이션이 아무 메시지 없이 다운된 경우에는 예외로 처리되지 않은 크로스-스레드가 있는 건 아닌지 확인해 보는 게 좋다.