Background thread doing DB access hangs UI
I've made a small utility program to test if a PC has a possibility to connect to a certain Oracle database.
To keep the UI responsive, and see the progress steps, I put the DB code in a background thread. To my amazement, the UI still hangs (but not as much).
It's really no big deal with this app, but I thought that the case is interesting in general, that the DB code in the thread hangs the UI thread!
private void bgwDataAccess_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bgw = sender as BackgroundWorker;
开发者_C百科 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;
}
Do you access the Oracle namespace anywhere in your code before this? This is just a guess, but maybe that pause is your application loading the required .dlls
You could try pre-loading the module. I use something like the code below in my applications. First I display a splash screen to show the app is loading and then call the snippet below to load all of the required dlls. That way, once the app is loaded, there's no pauses further down the line.
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*/)
{
}
}
}
Apologies for the C++/CLI syntax, but hopefully you can see how to convert that to C# - mine's a little rusty :-)
[Edit] I think this is pretty much 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
{
}
}
}
You can change query to "SELECT top 1 id FROM MYTABLE" and impact will be the same.
In case impact is not caused by those operations, you can use profiler to figure out which .net code causes impact.
精彩评论