方案: 我们有一个附加到DataAdapter(datatable)的DataGridView,我们在一个单独的线程中使用(adapter.fill(query,datatable))在datatable中加载数据(使用delegate和beginInvoke),一旦数据加载,我们附加了数据表到datagridview(在主线程中)
我们有办法检查fill()是否仍在执行并取消它。
真实场景: 用户单击用户名,相应的数据将加载到数据网格中。有时,用户不耐烦并点击另一个用户(这里我想取消之前的填充并开始新的填充)
更新: 我们保留两个DataApdater(和两个DataTables),我们将一个数据表附加到datagridview,并开始异步地将数据加载到另一个数据表。加载数据时,我们只需将datagridview绑定到我们刚刚填充的DataTable(并开始异步加载以前的数据)这样UI将始终获取当前数据(无需用户在UI上等待刷新或挂起)
答案 0 :(得分:1)
您可以为适配器构造函数提供SqlCommand并在其上调用Cancel方法。 有一个原始模板:
class Model
{
private SqlCommand loadUserCommand;
private DataTable userData;
public void LoadUser(string userId)
{
loadUserCommand = GetUserLoadCommandForUserID(userId);
userData = new DataTable("userData");
using (var adapter = new SqlDataAdapter(loadUserCommand))
{
adapter.Fill(userData);
}
}
public void AbortLoadUser()
{
if (loadUserCommand!= null)
loadUserCommand.Cancel();
}
private SqlCommand GetUserLoadCommandForUserID(string userId)
{
var connection = new SqlConnection("...");
var command = connection.CreateCommand();
...
}
}
答案 1 :(得分:0)
无法安全取消DataAdapter.Fill()
。
要解决此问题,一个选项是实现一种机制,可以忽略这些不需要的填充,因此不会反映在UI中。我建议在异步操作开始时递增计数器并将该状态传递给asyn操作。然后,您的异步操作可以在完成时针对当前计数器检查其计数器值。如果计数器不相等,则不要更新UI。
如果您看到用户在用户之间快速点击并且大量请求被丢弃的模式,那么实施一个计时器机制,只有当用户在选择中保持最短时间时才能检索数据。
答案 2 :(得分:0)
我做了一个快速搜索并找到了这个:cancel a DataAdapter.Fill似乎没有办法绕过处理异常,正如代码的作者所说。