执行数据库访问的后台线程挂起UI

时间:2011-02-03 09:59:07

标签: c# database multithreading oracle user-interface

我已经制作了一个小型实用程序来测试PC是否可以连接到某个Oracle数据库。

为了保持UI响应,并查看进度步骤,我将数据库代码放在后台线程中。令我惊讶的是,UI仍然悬而未决(但没有那么多)。

这个应用程序真的没什么大不了的,但我认为这个案例很有意思,线程中的DB代码挂起了UI线程!

    private void bgwDataAccess_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker bgw = sender as BackgroundWorker;

        try
        {
            bgw.ReportProgress(0, "Starting...\r\n");
            bgw.ReportProgress(0, "Active ConnectionString:\r\n");
            bgw.ReportProgress(0, Settings.Default.ConnctionString + "\r\n\r\n");

            OracleConnection con = new OracleConnection(Settings.Default.ConnctionString);
            OracleCommand cmd = new OracleCommand("SELECT Count(*) FROM MYTABLE", con);


            bgw.ReportProgress(0, "Opening db...\r\n");
            con.Open();
            bgw.ReportProgress(0, "Opened.\r\n\r\n");

            bgw.ReportProgress(0, "Executing SQL-query...\r\n");
            Object result = cmd.ExecuteScalar();
            bgw.ReportProgress(0, String.Format("Result: {0}\r\n\r\n", result.ToString()));

            con.Close();
        }
        catch (Exception)
        {
            throw;
        }
    }

    private void bgwDataAccess_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        txtResult.Text += e.UserState;           
    }

2 个答案:

答案 0 :(得分:1)

在此之前,您是否在代码中的任何位置访问Oracle命名空间?这只是猜测,但也许暂停是您的应用程序加载所需的.dll

您可以尝试预加载模块。我在我的应用程序中使用了类似下面的代码。首先,我显示一个启动画面,显示应用程序正在加载,然后调用下面的代码段来加载所有必需的dll。这样,一旦应用程序加载,就不再有停顿了。

void PreloadDLLs()
{
    Assembly^ assembly = Assembly::GetEntryAssembly();
    array<System::Reflection::AssemblyName^>^ referencedAssemblies = assembly->GetReferencedAssemblies();
    for each(System::Reflection::AssemblyName^ referencedAssemblyName in referencedAssemblies)
    {
        try
        {
            Assembly^ a = assembly->Load(referencedAssemblyName);
        }
        catch(System::Exception^ /*e*/)
        {

        }
    }
}

为C ++ / CLI语法道歉,但希望你能看到如何将它转换为C# - 我的有点生锈: - )

[编辑] 我认为这几乎是C#:

using System;
using System.Reflection;

private void PreloadDLLs()
{
    Assembly assembly = Assembly.GetEntryAssembly();
    System.Reflection.AssemblyName[] referencedAssemblies = assembly.GetReferencedAssemblies();
    foreach(System.Reflection.AssemblyName referencedAssemblyName in referencedAssemblies)
    {
        try
        {
            Assembly a = assembly.Load(referencedAssemblyName);
        }
        catch
        {

        }
    }
}

答案 1 :(得分:0)

您可以将查询更改为“SELECT top 1 id FROM MYTABLE”,影响将相同。

如果影响不是由这些操作引起的,您可以使用分析器来确定哪个.net代码会产生影响。