Loopsludge

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();
}



Re: Windows Forms General Results from a worker thread into main thread?

Loopsludge

Please allow me to append the following to the last post.

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




Re: Windows Forms General Results from a worker thread into main thread?

smithalovesdotnet

did you ever get an answer to this




Re: Windows Forms General Results from a worker thread into main thread?

nobugz

The code is okay although the ISynchronizeInvoke cast is unnecessary. The most likely reason for this problem: it takes time for the call to be marshaled to the UI thread. By the time it is ready to execute, the NewDataSet instance is probably already cleared or disposed. Use the Clone() method to avoid this problem.





Re: Windows Forms General Results from a worker thread into main thread?

JRQ

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);





Re: Windows Forms General Results from a worker thread into main thread?

smithalovesdotnet

Where would you suggest I use the Clone Within the refresh function




Re: Windows Forms General Results from a worker thread into main thread?

nobugz

For the argument to BeginInvoke(). Or try Invoke() instead.





Re: Windows Forms General Results from a worker thread into main thread?

Indian Ocean

 Loopsludge wrote:

       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();
        }

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,






Re: Windows Forms General Results from a worker thread into main thread?

nobugz

Initializing the delegate to "recursively" call the same function is fine. It is not in fact a recursive call because the delegate call is marshaled to the UI thread. And InvokeRequired will be False.





Re: Windows Forms General Results from a worker thread into main thread?

Keith Rome

Indian Ocean wrote:

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"]

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.






Re: Windows Forms General Results from a worker thread into main thread?

Indian Ocean

Keith Rome wrote:
Indian Ocean wrote:

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"]

From an OOP perspective, it can be argued that best practice would be using the "this.InvokeRequired" form mentioned rather than <controlobj>.InvokeRequired.

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,






Re: Windows Forms General Results from a worker thread into main thread?

Indian Ocean

Loopsludge,

Is your problem solved