繁体   English   中英

C#:从SqlDataReader填充DataTable并具有中断能力?

[英]C#: Populate DataTable from SqlDataReader with the ability to interrupt?

我想通过SqlDataReader填充DataTable对象,并具有中断操作的能力(例如,在用户要取消长时间运行的查询的情况下,通过u / i)。

不幸的是,我看不到任何带有CancellationTokenDataTable.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM