양식을 닫는 방법과 배경 작업자가 상호 작용하는 것으로 의심되는 일부 코드에서 이상한 버그를 관찰하고 있습니다. 여기 백그라운드 작업자를 사용할 때 양식 닫기를 올바르게 처리하는 방법은 무엇입니까?
는 잘못 잠재적 코드 :var worker = new BackgroundWorker();
worker.DoWork += (sender, args) => {
command();
};
worker.RunWorkerCompleted += (sender, args) => {
cleanup();
if (args.Error != null)
MessageBox.Show("...", "...", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
};
worker.RunWorkerAsync();
이 코드는 버튼이 눌러지는 형태의 방법으로 실행된다. command()가 느리면 실행하는 데 몇 초 정도 걸릴 수 있습니다.
사용자가 위의 코드를 실행하는 버튼을 누르면 실행됩니다. 완료되기 전에 양식이 닫힙니다.
문제는 cleanup()을 으로 호출하면 가끔이 발생하여 ObjectDisposedException이 발생합니다. 나는 "때때로"라고 말합니다. 이것은 내 컴퓨터에서 결코 일어나지 않기 때문입니다. command()가 완료되기 전에 양식이 닫히면 RunWorkerCompleted에 등록 된 처리기가 실행되지 않습니다. 다른 컴퓨터에서 처리기는 한 번 백 번 호출됩니다. 동료의 컴퓨터에서 거의 항상 호출됩니다. 분명히 처리기의 실행 확률은 컴퓨터의 나이/느려짐에 따라 증가합니다.
첫 번째 질문 :
이것은 BakgroundWorker의 예상되는 동작입니까? 양식에 대해 아무 것도 모른다는 것을 기대하지는 않습니다. "근로자"와 "이"양식을 연결하는 것을 볼 수있는 것이 아무것도 없기 때문입니다.
두 번째 질문 :
문제를 해결하려면 어떻게해야합니까? 내가 고려하고
가능한 해결책 :
- 시험의 경우 정리()를 호출하기 전에 (this.IsDisposed!). 그렇게해도 충분합니까? 아니면 정리가 실행되는 동안 양식을 처리 할 수 있습니까?
- try {} catch (ObjectDisposedException)에서 cleanup()에 대한 호출을 래핑하십시오. 나는 그런 종류의 접근법을 너무 좋아하지 않는다. 왜냐하면 나는 정리 (또는)에서 다른 관련이없는 버그로 인해 발생 된 예외를 잡을 수도 있고, 호출하는 메소드 중 하나를 예외로 잡을 수도 있기 때문이다.
- IsClosing 및 지연에 대한 처리기를 등록하거나 RunWorker Completed에 대한 처리기가 실행될 때까지 닫기를 취소하십시오.
관련이있을 수있는 추가 정보 : command()의 코드는 "this"의 GUI 개체에 대한 업데이트를 수행합니다. 이러한 업데이트는이 F 번호 함수 호출을 통해 수행됩니다 : 당신은 하나 개의 스레드 (작업자)에 의해 배치 된 컨트롤에 액세스하려고한다는 사실 이외의 BackgroundWorker
에 대한 연결을하지 않아도 언급
/// Run a delegate on a ISynchronizeInvoke (typically a Windows.Form).
let runOnInvoker (notification_receiver : ISynchronizeInvoke) excHandler (dlg : Delegate) args =
try
let args : System.Object[] = args |> Seq.cast |> Array.ofSeq
notification_receiver.Invoke (dlg, args) |> ignore
with
| :? System.InvalidOperationException as op ->
excHandler(op)
당신이 던진 GUI 업데이트 중 하나가 아니 었습니까? – CodesInChaos
당신은 "양식에 대해 아무 것도 모른다는 것을 기대하지 않을 것입니다. 제가 볼 수있는 것이"this "와"this "를"worker "와 연결시키는 것을 볼 수 없기 때문입니다." 그러나'명령'과'정리'가 아마 형태의 방법인가? – Jordi
CodeInChaos : command()에서 던져진 것이라면 args.Error의 예외와 함께 RunWorkerCompleted가 발생해야합니다. 그것은 여기서 일어나지 않습니다. – Joh