Dataset.Fill 时程序没有响应/反应
Posted
技术标签:
【中文标题】Dataset.Fill 时程序没有响应/反应【英文标题】:Program is not responding/reacting while Dataset.Fill 【发布时间】:2021-12-10 15:58:46 【问题描述】:我的程序窗口只要在 Dataset.fill 函数中就不能再移动或反应。
有人知道为什么会这样吗?
using (OracleCommand cmd = new OracleCommand(sqlQuery))
cmd.CommandType = CommandType.Text;
cmd.Connection = oraCon;
using (DataSet dSetHelper = new DataSet())
using (OracleDataAdapter dataAdapter = new OracleDataAdapter())
dataAdapter.SelectCommand = cmd;
if (!File.Exists(projPath + "/" + tableNameFromRow + "/" + tableNameFromRow + ".xml"))
currentTableName.Text = "Export: " + tableNameFromRow;
this.Refresh();
dataAdapter.Fill(dSetHelper);
dSetHelper.WriteXml(projPath + "/" + tableNameFromRow + "/" + tableNameFromRow + ".xml");
【问题讨论】:
【参考方案1】:如果你不使用任何任务或其他多线程方法,windows窗体运行一个线程。
可能您的查询响应时间很长。
因此,您的主线程无法响应其他进程,例如按钮单击或其他事件。
对于解决方案,您可以将代码带到任务块
var source = new CancellationTokenSource();
var token = source.Token;
var task = Task.Run(() => DoSomething(token), token);
您可以在此块中获取您的数据。
static void DoSomething(CancellationToken token)
///oracle connection, get data, fill etc etc
【讨论】:
【参考方案2】:有人知道为什么会这样吗?
是的,简单来说,您的程序是一个线程,其唯一工作是绘制 UI。它是运行任何按钮单击处理程序代码等的线程,它不应该长时间保持忙碌。当您运行 30 秒的数据库查询时,线程将在等待查询完成时停止绘制 UI,并且您的所有点击、拖动和按键都将进入等待线程处理它们的消息队列。几秒钟后,windows 可能会注意到 UI 线程已停止执行其保持队列清除的正常工作(窗口 UI 消息队列正在建立和建立而不是清除)并且它淡化窗口并显示“没有响应“在标题中。当 db 查询完成后,线程突然又开始处理 UI 消息,app 就活了
您不需要让您的 UI 线程长时间忙碌。不要让它完成耗时超过半秒的 IO 工作(磁盘、数据库)。对于更长的工作,您可以将您的方法转为async
(如果您需要更多帮助,请发布方法签名)并执行以下操作:
await Task.Run(_ => dataAdapter.Fill(dSetHelper); );
如果您填写大量数据,请考虑它可能产生的其他后果;也许使用阅读器从数据库中流式传输数据,而不是将其全部加载到数据集中。如果查询运行缓慢,或许可以寻找优化方法;将 UI 放在运行缓慢的查询上通常会将其交到用户手中,这可能意味着他们会在对运行时间很长感到沮丧时执行诸如敲击“运行查询”按钮之类的操作,从而使问题更加复杂..(考虑禁用该按钮查询运行时)
如果你想简化你的代码,你不需要using
一个数据集,你不需要提供一个命令/连接到一个数据适配器; DA 有一个构造函数,它接受一个 sql 和一个连接字符串,它们为您创建命令/连接,打开它并处理它。这意味着您可以将 DA 查询归结为:
using var da = new...(sql,con str);
var dt = new DataTable();
da.Fill(dt);
【讨论】:
以上是关于Dataset.Fill 时程序没有响应/反应的主要内容,如果未能解决你的问题,请参考以下文章