有一个查询最多可能需要一个小时才能完成。为了不阻塞用户界面,它通过任务。如果用户厌倦了等待,这个请求应该被取消。如何正确地做到这一点,以便连接不会在加载数据库时挂起一个小时,并且用户不会创建一堆它们?也许除了任务之外还有其他选择?
private void UpdateGrid(){
SomeRows rows;
Task task = new Task(() =>
{
rows = IDBConnectInstance.SelectRows();
});
task.ContinueWith(() =>
{
dataGridView.DataSource = rows;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
更新:
没有额外加的点,IDBConnectInstance本身就是一个来自第三方库的接口。即进入库函数IDBConnectInstance.SelectRows,停止等待完成。如果可以处理CancellationToken,问题就不会出现了。
IDBConnect
{
SelectRows();
}
public class DBConnect: IDBConnect
{
public List<SomeClass> SelectRows()
{
String query = "Очень долгий SELECT из БД";
List<SomeClass> result = new List<SomeClass>();
using(OracleConnection dbconn = new OracleConnection(ConnectionString))
{
dbconn.Open();
OracleCommand command = new OracleCommand(query, dbconn);
OracleDataReader reader = command.ExecuteReader();
while (reader.Read())
{
SomeClass someClass = new someClass()
{
SomeField = reader[0],
SomeField = reader[1],
...
}
result.Add(someClass);
}
reader.Close();
dbconn.Close();
}
return result;
}
}
到目前为止,只有一个想法返回Thread并使用已弃用的Thread.Abort();
引用MSDN:
因此,您可以尝试这样的拐杖:启动带有计时器的父任务,从中启动您的孩子。tayier过期后,取消parent,理论上会导致child的取消(如果它没有自己的取消逻辑©)
典型方法——两项任务。如果您需要“杀死”而不会失败,那么显式启动一个单独的线程并对其调用 Thread.Abort 是有意义的。
最好让用户能够根据命令取消。
我提供的代码针对取消的概念进行了简化。