크로스 스레드 작업이 잘못되었습니다. xxx 컨트롤이 자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다


c#으로 개발을 하다보면 '크로스 스레드 작업이 잘못되었습니다. xxx 컨트롤이 자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다' 이와 같은 에러가 발생할 수 있습니다. 컨트롤이 있는 스레드가 아닌 다른 스레드에서 컨트롤에 접근을해서 생긴 문제라고 하는데 전 따로 쓰레드를 만들지 않고 툴을 만들다가 폴더의 파일 변화 감지를 자동으로 하려고 FileSystemWatcher를 사용했고 폴더에 변화가 생기면 로그창에 로그를 찍으라고 했는데 이때 InvalidOperationException 예외가 발생하더군요. 내부적으로 등록한 이벤트가 쓰레드로 처리되는가 봅니다.

해결 방법은 크게 3가지가 있습니다.

CheckForIllegalCrossThreadCalls = false;

첫번째로 위 한 줄을 추가하면 해결이 가능합니다. 해당 예외는 debug에서만 발생하므로 이 한줄 추가로 예외를 무시할 수 있습니다.

두번째로 delegate와 Invoke를 사용해서 처리합니다.

delegate void FileWatcherDelegate(string text);
/// <summary>
/// 리스트 박스에 로그 출력
/// </summary>
/// <param name="strLog"></param>
public void AddLog(string strLog)
{
    try
    {
        if (this.patchLogList.InvokeRequired)
        {
            FileWatcherDelegate fileWatcherDelegate = new FileWatcherDelegate(AddLog);
            this.patchLogList.Invoke(fileWatcherDelegate);
        }
        else
        {
            this.patchLogList.Items.Add(strLog);
            this.patchLogList.SelectedIndex = this.patchLogList.Items.Count - 1;
        }
    }
    catch (System.Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK);
    }
}

컨트롤의 InvokeRequired가 true면 다른 스레드에서의 접근이 발생한 것이므로 딜리게이트를 통해 처리해야 합니다. 이때 Invoke가 활용 됩니다. 저는 딜리게이트로 해결 했습니다.

마지막 방법은 BackgroundWorker를 사용한 방법인데 이것은 아래 msdn 링크에 있는 것을 참고하시면 됩니다.

스레드로부터 안전한 방식으로 Windows Forms 컨트롤 호출

댓글

이 블로그의 인기 게시물

CMake Windows에 설치하기

'xxx.exe' 프로그램을 시작할 수 없습니다. 지정된 파일을 찾을 수 없습니다.