I have a C# dll which provides an event of SqlDependency Notification messages to clients via a delegate. The event fires ok and I get the expected data. The problem lies when I try to get the resulting dataset into a DataGridView without having to implement a manual refresh via button click. I'd like for this to automatically update upon change.
I'm thinking the reason is because the data is coming from a worker thread within the SqlDependency class and I have to create some means of marshalling it into the main (gui) thread.
Below is my first whack at the event handler but for some reason it does not work. That is I still have to mash a refresh button. Can anyone offer a suggestion
void ExcepNotification_NewExceptionNotification(DataSet NewDataSet)
{
// This event will occur on a thread pool thread.
// Updating the UI from a worker thread is not permitted.
// The following code checks to see if it is safe to
// update the UI.
ISynchronizeInvoke i = (ISynchronizeInvoke)this;
// If InvokeRequired returns True, the code
// is executing on a worker thread.
if (i.InvokeRequired)
{
// Create a delegate to perform the thread switch.
NewExceptionNotificationHandler tempDelegate = new NewExceptionNotificationHandler(ExcepNotification_NewExceptionNotification);
object[] args = { NewDataSet };
// Marshal the data from the worker thread
// to the UI thread.
i.BeginInvoke(tempDelegate, args);
return;
}
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = NewDataSet;
dataGridView1.DataMember = NewDataSet.Tables[0].ToString();
}

Results from a worker thread into main thread?
Don Eddleman
Paul Lemon
Alastair Q
Loopsludge,
Is your problem solved
Elhanna
Hi,
Sorry but where OOP come here, that i didnt understand...
I mean, the variables are local to the form and must be "private" so outsider will not touch anything in it for InvokeRequired. Only the delegate will be called from outside so except that delegate method all can be private and my point was not about OOP when i said <controlobj>.InvokeRequired, it was good programming practice to use only those variables which is targetted... like in lock statement its good to use a perticular object instead of "this".
Thats what i meant to say, If its wrong, please correct me,
Thanks,
Eric Eichler
From an OOP perspective, it can be argued that best practice would be using the "this.InvokeRequired" form mentioned rather than <controlobj>.InvokeRequired.
The fact that the control requires actual UI updates to execute on the same thread on which it was created is an implementation detail of that control, and should be hidden by external parties. In this way, calling code can remain oblivious to the internal thread context requirement, and just invoke the method directly. This is similar to the "best practice" of using the property accessor get/set methods to guard threading-sensitive fields. Callers don't know and don't care about the locking rules - they just interact with the properties.
Zach7
i.InvokeRequired - this part intrigues me, will it really toggles to false when the current pass came from the call to i.BeginInvoke()
I never tried this somewhat recursive approach. When I have to do this, I always follow this template;
if (this.InvokeRequired)
{
// create a delegate to a worker method, ex. RefreshGrid
// setup arguments
i.BeginInvoke(RefreshGridDelegate, args)
}
else // just call the worker method directly
RefreshGrid(args);
Sweeps78
If I set a breakpoint at the i.BeginInvode(...) line and step through it, the grid updates as it is supposed to.
Any suggestions
Thanks in advance!
Loopsludge
Derek at Potters Clay
My points,
1. Why you are assigning the same method in your delegate In this way again it will call this method, It should not be like this IMHO,
2. The following code should work, [The best practice would be <controlobj>.InvokeRequired, the controlobj is a control which you want to update somehow, instead of using "this.InvokeRequired"]
void
ExcepNotification_NewExceptionNotification(DataSet NewDataSet){
if (dataGridView1.InvokeRequired){
NewExceptionNotificationHandler tempDelegate = new NewExceptionNotificationHandler(UpdateDGView); object[] args = { NewDataSet };dataGridView1.BeginInvoke((tempDelegate, args);
}
else{
UpdateDGView(NewDataSet);
}
}
private void UpdateDGView(DataSet NewDataSet){
dataGridView1.AutoGenerateColumns =
true;dataGridView1.DataSource = NewDataSet;
dataGridView1.DataMember = NewDataSet.Tables[0].ToString();
}
I assumed the following at class level or accessible in the class,
delegate
void NewExceptionNotificationHandler(DataSet NewDS);DataGridView dataGridView1 = new DataGridView();
If you still have problem, give the exception stack trace,
HTH,
mpipe again
Spangltk
nkojuharov