[英]C#: Populate DataTable from SqlDataReader with the ability to interrupt?
我想通过SqlDataReader
填充DataTable
对象,并具有中断操作的能力(例如,在用户要取消长时间运行的查询的情况下,通过u / i)。
不幸的是,我看不到任何带有CancellationToken
的DataTable.Load()
重载。
有没有一种干净的方法来实现这一目标?
(我唯一的想法是使用线程,看看Thread.Interrupt()
是否能解决问题,如果不是,那么就去看Thread.Abort()
但这似乎并不Thread.Abort()
)。
您可以使用任务和取消令牌。 当然,您将必须手动填充DataTable,而不是使用Load方法。
private void FillTable(CancellationToken token)
{
var reader = new SqlDataReader();
var dt = CreateDataTable();
while(reader.Read() && !token.IsCancellationRequested)
{
var row = dt.NewRow();
// fill row from reader....
dt.Rows.Add(row);
}
}
您将使用这种方法:
CancellationTokenSource tokenSource = new CancellationTokenSource();
Task.Factory.StartNew(() => FillTable(tokenSource.Token), tokenSource.Token);
然后您可以取消操作:
tokenSource.Cancel();
与SqlDataAdapter耦合,您可以处理DataTable RowChanged事件,并引发异常或关闭数据适配器的连接,这将引发InvalidOperationException。
看下面的示例( source ):
private BackgroundWorker worker;
private DataTable table;
private void button2_Click(object sender, EventArgs e)
{
if (worker != null)
{
worker.CancelAsync();
}
}
private void button1_Click(object sender, EventArgs e)
{
this.worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show(this.table.Rows.Count.ToString());
}
[System.Diagnostics.DebuggerStepThrough]
void worker_DoWork(object sender, DoWorkEventArgs e)
{
this.table = new DataTable();
using (SqlConnection connection= new SqlConnection())
using (SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM table", connection))
{
table.RowChanged += new DataRowChangeEventHandler(table_RowChanged);
da.Fill(table);
}
}
[System.Diagnostics.DebuggerStepThrough]
void table_RowChanged(object sender, DataRowChangeEventArgs e)
{
if (worker.CancellationPending)
{
throw new ApplicationException("Canceled"); // throw a spanner in the works
}
Thread.Sleep(5); // Just slow things down for testing
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.