程序不是 responding/reacting 而 Dataset.Fill

Program is not responding/reacting while Dataset.Fill

我的问题是我的程序 window 只要在 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");
            }
        }
    }
}

如果您不使用任何任务或其他多线程方法,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
}

Have anyone an idea why that might be?

是的,简单来说,您的程序有一个线程,其唯一的工作就是绘制 UI。它是 运行 任何按钮单击处理程序代码等的线程,它不应该长时间保持忙碌。当你 运行 一个 30 秒的数据库查询时,线程将在等待查询完成时停止绘制 UI,你所有的点击、拖动和按键都会进入这个 queues 等待线程处理的消息。几秒钟后,windows 可能注意到 UI 线程已停止正常工作以保持 queue 清晰(window UI 消息queue 正在不断增加而不是清除)并且它淡化 window 并在标题中添加“无响应”。当数据库查询完成时,线程突然再次开始处理 UI 消息,应用程序开始运行

您不需要让您的 UI 线程长时间忙碌。不要让它做 IO 工作(磁盘、数据库),这需要比半秒更长的时间。对于更长的工作,您可以将您的方法 async(post 方法签名,如果您需要更多帮助)并执行:

await Task.Run(_ => { dataAdapter.Fill(dSetHelper); });

如果您填写了大量数据,请考虑它可能产生的其他后果;也许使用 reader 从数据库流式传输数据,而不是将其全部加载到数据集中。如果查询速度慢运行ning,也许想办法优化它;在缓慢的 运行ning 查询上粘贴 UI 通常会将其交到用户手中,这可能意味着他们会在感到沮丧时做一些事情,例如敲击 运行 查询按钮花了很长时间,使问题复杂化..(考虑在查询 运行s 时禁用按钮)

如果您想简化代码,您不需要 using 数据集,也不需要向数据适配器提供 command/connection; DA 有一个构造函数,它接受一个 sql 和一个连接字符串,它们为你生成 command/connection,打开并处理它。这意味着您可以将 DA 查询归结为如下内容:

using var da = new...(sql,con str);
var dt = new DataTable();
da.Fill(dt);