IT Share you

BackgroundWorker의 처리되지 않은 예외

shareyou 2020. 11. 16. 23:11
반응형

BackgroundWorker의 처리되지 않은 예외


BackgroundWorker 개체를 사용하여 장기 실행 작업을 수행하는 작은 WinForms 앱이 있습니다.

백그라운드 작업은 일반적으로 누군가가 다시 생성되는 파일을 열었을 때 가끔 예외를 발생시킵니다.

코드가 IDE에서 실행되는지 여부에 관계없이 .NET은 처리되지 않은 예외가 발생했음을 사용자에게 알리는 오류 대화 상자를 표시합니다. 릴리스 구성을 사용하여 코드를 컴파일해도 이것도 변경되지 않습니다.

MSDN 에 따르면 :

작업에서 코드에서 처리하지 않는 예외가 발생하면 BackgroundWorker는 예외를 포착하여 RunWorkerCompleted 이벤트 처리기로 전달합니다. 여기서 System.ComponentModel .. ::. RunWorkerCompletedEventArgs의 Error 속성으로 노출됩니다. Visual Studio 디버거에서 실행중인 경우 처리되지 않은 예외가 발생한 DoWork 이벤트 처리기의 지점에서 디버거가 중단됩니다.

이러한 예외는 때때로 throw 될 것으로 예상하며 DoWork가 아닌 RunWorkerCompleted 이벤트에서 처리하고 싶습니다. 내 코드가 제대로 작동하고 RunWorkerCompleted 이벤트 내에서 오류가 올바르게 처리되지만 "처리되지 않은 예외"가 발생하는 것을 불평하는 .NET 오류 대화 상자를 중지하는 방법을 알아낼 수는 없습니다.

BackgroundWorker가 자동으로 오류를 포착해야하지 않나요? MSDN 설명서에 나와 있지 않습니까? RunWorkerCompletedEventArgs의 Error 속성에 예외가 계속 발생하도록 허용하면서이 오류 처리되고 있음을 .NET에 알리려면 어떻게해야 합니까?


설명하는 것은 BackgroundWorker의 정의 된 동작이 아닙니다. 당신은 뭔가 잘못하고 있다고 생각합니다.

다음은 BackgroundWorker가 DoWork 에서 예외 를 처리하고 RunWorkerCompleted 에서 예외를 사용할 수 있도록 하는 작은 샘플입니다 .

var worker = new BackgroundWorker();
worker.DoWork += (sender, e) => 
    { 
        throw new InvalidOperationException("oh shiznit!"); 
    };
worker.RunWorkerCompleted += (sender, e) =>
    {
        if(e.Error != null)
        {
            MessageBox.Show("There was an error! " + e.Error.ToString());
        }
    };
worker.RunWorkerAsync();

내 심령 디버깅 기술이 문제를 드러내고 있습니다 .RunWorkerCompleted 핸들러에서 e.Result에 액세스하고 있습니다 .e.Error가있는 경우 e.Result에 액세스하지 않고 처리해야합니다. 예를 들어 다음 코드는 불량, 불량, 불량이며 런타임에 예외를 throw합니다.

var worker = new BackgroundWorker();
worker.DoWork += (sender, e) => 
    { 
        throw new InvalidOperationException("oh shiznit!"); 
    };
worker.RunWorkerCompleted += (sender, e) =>
    {
        // OH NOOOOOOOES! Runtime exception, you can't access e.Result if there's an
        // error. You can check for errors using e.Error.
        var result = e.Result; 
    };
worker.RunWorkerAsync();

다음은 RunWorkerCompleted 이벤트 처리기의 적절한 구현입니다.

private void RunWorkerCompletedHandler(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null)
    {
       DoSomethingWith(e.Result); // Access e.Result only if no error occurred.
    }
}

VOILA, 당신은 런타임 예외를받지 않을 것입니다.


MSDN 텍스트에 추가 합니다 .

작업에서 코드에서 처리하지 않는 예외가 발생하면 BackgroundWorker는 예외를 포착하여 RunWorkerCompleted 이벤트 처리기로 전달합니다. 여기서 System.ComponentModel .. ::. RunWorkerCompletedEventArgs의 Error 속성으로 노출됩니다. Visual Studio 디버거에서 실행중인 경우 디버거는 처리되지 않은 예외가 발생한 DoWork 이벤트 처리기의 지점에서 중단됩니다.

... 그리고 디버거는 "~ Exception was unhandled by user code"로 예외를보고합니다.

솔루션 : 디버거에서 실행하지 마십시오. 예상대로 작동합니다. e.Error에서 예외가 발견되었습니다.


이것은 오래된 질문이지만 인터넷 검색 중에 동일한 증상을 발견했습니다. 같은 이유로 다른 사람이 발견 한 경우 게시합니다.

Judah's answer is right, but it isn't the only reason the "unhandled exception in user code" dialog can appear. If an exception is thrown from inside a constructor on the background thread then that exception will cause the dialog immediately, and won't be passed to the RunWorkerCompleted event. If you move the offending code outside of any constructors (to any other method) it works as expected.


[Edit]

Judah has a great point. My example pointed out the specifics of handling the error but my code would actually cause another exception if an exception was never hit in the DoWork method. This example is OK due to the fact that we are specifically showing the error handling capabilities of the BackgroundWorker. However if you are not checking the error parameter against null then this could be your issue.

[/Edit]

I don't see the same results. Can you post a little code? Here is my code.

private void Form1_Load(object sender, EventArgs e)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    worker.RunWorkerAsync();
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Will cause another exception if an exception didn't occur.
    // We should be checking to see if e.Error is not "null".
    textBox1.Text = "Error? " + e.Error;
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i < 10; i++)
    {
        if (i < 5)
        {
            Thread.Sleep(100);
        }
        else
        {
            throw new Exception("BOOM");
        }   
    }
}

Program Output:

Error? System.Exception: BOOM at BackgroundException.Form1.worker_DoWork(Object sender, DoWorkEventArgs e) in D:\Workspaces\Sandbox\BackgroundException\BackgroundException\Form1.cs:line 43 at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e) at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)

귀하의 질문과 유사한 흥미로운 기사입니다. 예외 처리에 대한 섹션이 있습니다.

http://www.developerdotstar.com/community/node/671


나는 같은 문제가 있었고 인터넷 검색 후이 주제를 찾기 전에 이미 유다 답변을 적용하고있었습니다.

글쎄, imo the Judah 대답은 부분적으로 정확합니다. 여기서 더 나은 답을 찾았 습니다.

디버거가 제대로 작동합니다. "실제 조건"에서 응용 프로그램을 실행하면 RunWorkerCompleted가 예상대로 예외를 처리하고 응용 프로그램 동작도 예상됩니다.

이 답변이 도움이 되었기를 바랍니다.

참고 URL : https://stackoverflow.com/questions/1044460/unhandled-exceptions-in-backgroundworker

반응형