c# - 在 BackgroundWorker 中停止查询阅读器的好方法是什么?
问题描述
我开始使用BackgroundWorker进行尝试,我想知道如何停止返回对象 列表的查询,这可能需要一些时间才能执行。
我想我无法停止服务器上的查询,但我特别要寻找的是停止读取包含此查询结果的SqlDataReader 。
这是我的 BackgroudnWorker 的代码示例和示例查询:
public partial class Form1 : Form
{
private BackgroundWorker worker;
public Form1 (Point location)
{
this.Location = location;
InitializeComponent();
worker = new BackgroundWorker
{
WorkerSupportsCancellation = true,
};
worker.DoWork += this.Worker_DoWork;
worker.RunWorkerCompleted += this.Worker_RunWorkerCompleted;
}
#region Form
private void ButtonBack_Click (object sender, EventArgs e)
{
if (worker.IsBusy && !worker.CancellationPending)
{
worker.CancelAsync();
}
this.Close();
}
private void TextBoxSearch_TextChanged (object sender, EventArgs e)
{
while (worker.IsBusy)
{
if (worker.IsBusy && !worker.CancellationPending)
{
worker.CancelAsync();
}
}
worker.RunWorkerAsync();
}
#endregion
#region Worker
private void Worker_RunWorkerCompleted (object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
if (worker.IsBusy && !worker.CancellationPending)
{
worker.CancelAsync();
}
Console.WriteLine(e.Error.Message);
}
}
private void Worker_DoWork (object sender, DoWorkEventArgs e)
{
if (!worker.CancellationPending)
{
// Where I'd like to cut the IEnumerable if worker.CancellationPending to shorten time of process
foreach (LigneHS ligne in GetLignesHS(worker.CancellationPending))
{
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
// Do work
}
}
else
{
e.Cancel = true;
return;
}
}
#endregion
// Sample query
internal static IEnumerable<LigneHS> GetLignesHS (bool cancellationPending)
{
string requete = "SELECT * FROM [MY_TABLE] ORDER BY [date] DESC";
SqlConnection conn = BDD.OpenBDD16();
SqlCommand command = new SqlCommand(requete, conn);
List<LigneHS> lignes = new List<LigneHS>();
LigneHS ligne = new LigneHS();
try
{
if (!cancellationPending)
{
SqlDataReader reader = command.ExecuteReader();
while (reader.Read() && !cancellationPending)
{
ligne = new LigneHS();
if (reader["id"] != DBNull.Value)
{
ligne.Id = Convert.ToInt32(reader["id"]);
// filtering null values for every column
lignes.add(ligne);
// tried to add the yield return here, but can't inside a try-catch
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("GetLignesHS : " + ex.Message);
}
finally
{
command.Dispose();
conn.Close();
}
return lignes;
}
}
就像这里一样,如果要求工作人员停止,则查询的 cancelPending 不会更新。
如果 BackgroundWorker 被要求停止,我首先想到使用yield return 来中断 foreach。但是,我在处理查询时使用了 try-catch,所以我不能。
我知道像使用直线程时那样使用CancellationToken会起作用,但我想知道这是否是实现我想要的最佳方式。
解决方案
推荐阅读
- discord.js - discord.js 发现返回未定义
- c# - c#发布的win表单应用程序源代码别人可读吗?
- java - 在子类的构造函数中抛出异常
- node.js - 如何使用cheerio循环结果
- http-live-streaming - 将 AAC 的 avcodec 配置配置为 HLS/MPEG-TS([mpegts @ 0x7fc4c00343c0] AAC 比特流不是 ADTS 格式并且缺少额外数据)
- java - 无法将 JSON 字符串转换为对象?
- javascript - Sequelize 和 Postgres - 无法实现外键约束
- c# - 如何在 Unity 3D 上正确配置触摸?
- python - 如何在循环中创建模型字段?
- reactjs - 如何在 Reactjs 中使用路由器包装多个上下文提供程序