C# 如何处理缺少调用的方法 public void RefreshData() { //这是在UI线程上调用的 列出数据源; GetDsDelegate调用者=GetDs; BeginInvoke(输出数据源,刷新回调,null); } 私有无效刷新回调(IAsyncResult ar) { //这是在工作线程上调用的 尝试 { var result=(AsyncResult)ar; var caller=(GetDsDelegate)result.AsyncDelegate; 列出数据源; var success=caller.EndInvoke(out-dataSource,ar); 如果(成功) { BeginInvoke(新操作(SetGridDataSource),dataSource); } } 接住 { //注意:调用RefreshData后,此表单可能会关闭 //但是在GetDs返回之前,SetGridDataSource方法不再存在。 //未捕获此错误将导致整个应用程序终止。 } 私有void SetGridDataSource(列表数据源) { //这是在UI线程上调用的 dataGrid.DataSource=数据源; }
RefreshData、RefreshCallback和SetGridDataSource都是windows窗体类的方法。调用RefreshData使用GetDsDelegate委托调用外部方法GetDs。当GetDs完成时,它调用RefreshCallback(现在在单独的线程上)。最后,调用SetGridDataSource以完成更新 除非GetDs被延迟并且表单关闭,否则所有这些都可以正常工作。然后当GetDs完成并调用RefreshCallback时,SetGridDataSource不再存在 除了显示的try/catch块之外,还有更好的方法来处理这种情况吗?我更愿意防止错误而不是忽略它。有更好的模式可以使用吗 编辑C# 如何处理缺少调用的方法 public void RefreshData() { //这是在UI线程上调用的 列出数据源; GetDsDelegate调用者=GetDs; BeginInvoke(输出数据源,刷新回调,null); } 私有无效刷新回调(IAsyncResult ar) { //这是在工作线程上调用的 尝试 { var result=(AsyncResult)ar; var caller=(GetDsDelegate)result.AsyncDelegate; 列出数据源; var success=caller.EndInvoke(out-dataSource,ar); 如果(成功) { BeginInvoke(新操作(SetGridDataSource),dataSource); } } 接住 { //注意:调用RefreshData后,此表单可能会关闭 //但是在GetDs返回之前,SetGridDataSource方法不再存在。 //未捕获此错误将导致整个应用程序终止。 } 私有void SetGridDataSource(列表数据源) { //这是在UI线程上调用的 dataGrid.DataSource=数据源; },c#,asynchronous,C#,Asynchronous,RefreshData、RefreshCallback和SetGridDataSource都是windows窗体类的方法。调用RefreshData使用GetDsDelegate委托调用外部方法GetDs。当GetDs完成时,它调用RefreshCallback(现在在单独的线程上)。最后,调用SetGridDataSource以完成更新 除非GetDs被延迟并且表单关闭,否则所有这些都可以正常工作。然后当GetDs完成并调用RefreshCallback时,SetGridDataSource不
当我看到错误时,很明显将
if(success)
更改为if(success&&IsHandleCreated)
以防止这种情况发生,但看起来我还是做错了什么,或者至少有点尴尬。我还可以用just Invoke替换第二个BeginInvoke,这样就不需要EndInvoke。我喜欢将逻辑从表单中移开的想法,但我看不出结果会有什么变化。我认为BackgroundWorker也会有同样的结果问题;回调不再可访问。我想可能会引发一个事件并产生结果,但这似乎有点抽象。请您再详细说明一点或提供一个示例。该方法确实存在。表单已关闭的事实不会改变类或其方法。如果您发布了确切的异常,您将获得,它可以帮助某人提供更准确的帮助
我猜当您试图在窗体或其控件关闭后对其执行某些操作时,您会遇到一个ObjectDisposedException
如果是这种情况,您只需增强逻辑,并在调用SetGridDataSource之前检查表单是否已关闭或释放
也就是说,您的设计似乎存在一些问题
BeginInvoke
上调用EndInvoke
BackgroundWorker
之类的工具,而不是链接BeginInvoke
调用catch
,并通过忽略任何抛出的异常而不重试来处理异常,这是一个非常糟糕的主意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;
}
.NET 4编译器是否支持最后一个推理示例?我非常确定它在.NET 3.5中不起作用。感谢您的回答。调用SetGridDataSource会生成“在创建窗口句柄之前,无法对控件调用Invoke或BeginInvoke”异常。鉴于窗体已关闭,这对我来说是有意义的。这是一个无法解决的争用条件,在所有工作线程完成运行之前,您不能允许窗体关闭。使用BackgroundWorker可以更轻松地完成此操作。
BeginInvoke(new Action<List<ds>>(SetGridDataSource), dataSource);
BeginInvoke(SetGridDataSource, dataSource);