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 时程序没有响应/反应的主要内容,如果未能解决你的问题,请参考以下文章

简单的 ncurses 应用程序对箭头键没有反应

在移动浏览器中打开时反应材料 ui 没有响应

反应 onClick 事件处理程序没有触发......?

在 PowerShell 中如何解决 DataSet.Fill 中的异常?

按钮对点击没有反应

反应钩子第一次没有设置状态