Reputation: 16685
I have a program that makes some hefty calls to the database and then updates the UI. This is causing problems because for most of the time it means that the UI in not responsive. I therefore decided that I wanted to put the function calls that access the database and update the UI in a separate thread, so now I have something like this:
private delegate void CallAsyncDelegate();
private void CallGetDBValues()
{
// Call GetDatabaseValues in new thread
CallAsyncDelegate callGetDatabaseValues = new
CallAsyncDelegate(GetDatabaseValues);
BeginInvoke(callGetDatabaseValues);
}
private void GetDatabaseValues()
{
// Get lots of data here
// Update UI here
}
...
However, it seems to make no difference whatsoever to the UI. I read somewhere that if the code to be run in a separate thread needed to update the UI then this was how the call should be made - is this correct? Am I doing something wrong?
Upvotes: 1
Views: 2302
Reputation: 23157
You may be better served using the BackgroundWorker
that is built-in to the .NET framework.
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.WorkerReportsProgress = true;
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// update UI with status
label1.Text = (string)e.UserState
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Check for cancel
if(e.Cancelled)
{
//Handle the cancellation.
{
//Check for error
if(e.Error)
{
//Handle the error.
}
// Update UI that data retrieval is complete
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
// Get data
//foreach to process data
//Report progress
bw.ReportProgress(n, message);
}
Here's a link to the MSDN article on how to use the BackgroundWorker for additional details. Thanks to Henk Holterman for the suggestion to include this:
http://msdn.microsoft.com/en-us/library/cc221403%28VS.95%29.aspx
Upvotes: 3
Reputation: 2151
I'm not sure of the syntax.. but the sytax I'm more familiar with is something like:
public delegate object myDelegate(object myParam);
Public class MyClass
{
public static void Main()
{
myDelegate d = new myDelegate(myMethod);
d.BeginInvoke ( new object() );
}
static void myMethod(object myParam)
{
// do some work!!
return new object);
}
}
Upvotes: 0
Reputation: 4867
BeginInvoke
and Invoke
means to run the code on the UI thread. In this case if you are calling CallGetDBValues()
from the UI thread you are not going to gain anything.
Usually you will create a BackgroundWorker
or background thread that will do the heavy lifting and it will Invoke back to the UI thread the values that need to be updated.
A BackgroundWorker
will probably be the better solution (see Robaticus's answer), but here is a background thread version.
private delegate void CallAsyncDelegate();
private void button_Click( object sender, EventArgs e )
{
Thread thread = new Thread( GetDBValues );
thread.IsBackground = true;
thread.Start();
}
private void GetDBValues()
{
foreach( ... )
{
Invoke( new CallAsyncDelegate( UpdateUI ) );
}
}
private void UpdateUI()
{
/* Update the user interface */
}
Upvotes: 1
Reputation: 77536
In the "// Update UI here", make sure to use Control.Invoke to actually do the work -- it's imperative that the UI only be "touched" by the UI-thread, and this only happens when you use Control.Invoke.
Upvotes: 1