【发布时间】:2017-11-17 23:24:33
【问题描述】:
我正在使用以下代码从并行线程将文档加载到 datagridview 中:
在块内Task.Run(() => {});
当我关闭表单时,我得到 ObjectDisposedException Cannot access a disposed object. 看起来 if (IsDisposed || Disposing) 失败并且代码尝试添加一行,同时 Disposing 已变为 true。
我可以捕捉到这个异常,但它很脏。
在关闭表单时添加启用标志以检查表单是否已关闭也不起作用。它的行为方式似乎与this.Disposing
在if (this.IsDisposed || this.Disposing) 之前添加Thread.Sleep(5); 似乎足以避免引发异常,但我不确定如果运气不好是否可以引发异常。
避免此问题的最佳做法可能是什么?
foreach (var doc in docList)
{
if (this.InvokeRequired)
{
if (IsDisposed || Disposing || dgv.IsDisposed || dgv.isposing) return;
this.Invoke(new MethodInvoker(() => { dgv.Rows.Add(doc.Name); }));
}
}
【问题讨论】:
-
也许你只是想隐藏表单?
-
您不会将行异步添加到网格视图中。您不能将行异步添加到 gridview 或任何其他 UI 元素。
Invoke表示“在 UI 线程上运行”。这段代码只是浪费了一个后台线程,在 UI 线程上以最慢的方式添加行,每次添加行时都强制重绘。 -
您应该删除此代码的全部,并将gridview 绑定到包含数据的集合或数据表。到底有多少数据?人类不能一次看到 100 行,你也不能显示它们。如果您有大量数据,请使用分页和虚拟滚动来仅加载需要的内容
-
此外,不要使用
async void,除非在事件处理程序中。不返回结果的异步方法的签名是async Task。你不能等待、停止或处理任何以async void运行的东西 -
您的实际问题是什么?你为什么要“异步加载网格”?你遇到性能问题了吗?您是否在消息到达后立即添加消息?您是否试图一次显示太多东西?还有什么?不管它是什么,自从 15 年前 .NET 1.0 出现以来,就有一些技术可以处理它。没有涉及
async
标签: c# winforms async-await task objectdisposedexception