public void RefreshData()
{
// this is called on UI thread
List<ds> dataSource;
GetDsDelegate caller = GetDs;
caller.BeginInvoke(out dataSource, RefreshCallback, null);
}
private void RefreshCallback(IAsyncResult ar)
{
// this is called on worker thread
try
{
var result = (AsyncResult)ar;
var caller = (GetDsDelegate)result.AsyncDelegate;
List<ds> dataSource;
var success = caller.EndInvoke(out dataSource, ar);
if (success)
{
BeginInvoke(new Action<List<ds>>(SetGridDataSource), dataSource);
}
}
catch
{
// NOTE: It's possible for this form to close after RefreshData is called
// but before GetDs returns thus the SetGridDataSource method no longer exists.
// Not catching this error causes the entire application to terminate.
}
private void SetGridDataSource(List<ds> dataSource)
{
// this is called on UI thread
dataGrid.DataSource = dataSource;
}
RefreshData, RefreshCallback 및 SetGridDataSource는 모두 Windows Form 클래스의 메서드입니다. RefreshData를 호출하면 GetDsDelegate 대리자를 사용하여 GetDs 메서드가 호출됩니다. GetDs가 완료되면 RefreshCallback (별도의 스레드에 있음)이 호출됩니다. 마지막으로 SetGridDataSource가 호출되어 업데이트가 완료됩니다.누락 된 호출 된 메서드를 처리하는 방법
GetDs가 지연되고 양식이 닫히지 않는 한 모든 것이 제대로 작동합니다. GetDs가 완료되고 RefreshCallback을 호출하면 SetGridDataSource가 더 이상 존재하지 않습니다.
표시된 try/catch 블록 이외의 다른 조건을 처리하는 더 좋은 방법이 있습니까? 오류를 무시하는 대신 오류를 방지하는 것이 좋습니다. 더 나은 패턴을 사용할 수 있습니까?
편집
나는 오류가, 그것을 방지하기 위해 if (success && IsHandleCreated)
-if (success)
을 변경 명백 것으로 보이지만, 내가 뭔가 잘못하고, 또는 적어도 어색한 것 같은 여전히 보인다 것처럼. 두 번째 BeginInvoke를 Invoke로 바꿀 수도 있으므로 EndInvoke는 필요하지 않습니다. 논리를 폼에서 옮기는 아이디어가 마음에 들지만 결과가 어떻게 변하는 지 알지 못합니다. 나는 BackgroundWorker도 같은 문제가 있다고 생각할 것이다. 그 콜백되고 더 이상 액세스 할 수 없습니다. 나는 사건이 결과로 제기 될 수 있다고 생각하지만, 그것은 약간 추상적으로 보인다. 조금 더 자세히 설명해 주시고 예를 들려 주시겠습니까?
이 해결 못하는 경쟁 조건이다, 당신은 할 수 없습니다 모든 작업자 스레드가 실행을 마칠 때까지 양식을 닫을 수 있습니다. 이것은 BackgroundWorker로 훨씬 쉽게 수행 할 수 있습니다. –