Main Site Documentation

Program.CheckAndInvoke problem


#1

Hi to all,
I develop an application that raise some events to notify changing.

I follow the standard pattern to raise an event using a CheckAndInvoke on Program object.

Some times the event not fired on subscriber, but perhaps I don’t understand sometings.
Instead if I call directly the event, its fired correctly.

Is correct to use CheckAndInvoke or call directly the events?

Thanks to all


#2

You should just throw events. If you want synchronous invocation, you call event_name.Invoke(), or just event_name(). If you want asynchronous invocation you call event_name.BeginInvoke().

If the event is triggered from the thread other than that belonging to the dispatcher, and you need to refresh GUI display elements, you have to call dispatcher.Invoke() to marshall your event handler onto the dispatcher thread. You can find out if this is necessary by calling dispatcher.CheckAccess().


#3

Thanks MoonDragon,
If I correctly undestand, I used CheckAndInvoke if I would to raise the event into dispatcher thread, otherwise I need to use _event.begininvoke() (sfortunatly not supported in Hydra) or _event()

Correct?

Thanks


#4

Don’t use CheckAndInvoke.

Whatever you do, just throw your events normally. I could be wrong, but I also don’t think that BeginInvoke has anything to do with Hydra. It’s basic .NETMF functionality. All it does is thrown an event on its own separate thread, so that the thread where you throw an event from can continue right away.

Dispatcher is a separate issue. Dispatcher runs on your main application thread. The one that was first started when your application started. It is where your main “message pump” runs. Certain code MUST run in that specific thread. If you happen to have such code, then you would use Dispatcher.Invoke method to marshall such code onto the dispatcher thread. You can find out if you need to marshall, by calling Dispatcher.CheckAccess() method.

I suspect that CheckAndInvoke method wraps the two functionalities together. It calls CheckAccess first, then Invoke if necessary. But in its documentation it says it’s a specialized method. Do not use it. You do not need it. If you know you need to execute some code in dispatcher thread, then call Invoke yourself.


#5

I would get the latest Gadgeteer library code, which includes source code for most of the available modules, and see how they do dispatching to the main event queue.


#6

It is important to use the standard event-throwing pattern to make sure the event ends up in the Dispatcher thread. That way the users of your modules don’t end up facing cross-thread invocation exceptions or unwanted race conditions.

The latest BETA Gadgeteer Module Template (included in the GadgeteerBuilderTemplates.msi) clarifies this pattern a bit. Please note that these templates are still work-in-progress and I would not use them to generate a public module installer just yet, but you can get and download the package from the codeplex site to get a better understanding of how to throw events, Gadgeteer-style.

The relevant bits from a template-generated module look like this:


 /// <summary>
        /// Represents the delegate that is used to handle the <see cref="TestModuleHigh"/>
        /// and <see cref="TestModuleLow"/> events.
        /// </summary>
        /// <param name="sender">The <see cref="TestModule"/> object that raised the event.</param>
        /// <param name="state">The state of the TestModule</param>
        public delegate void TestModuleEventHandler(TestModule sender, TestModuleState state);

        /// <summary>
        /// Raised when the state of <see cref="TestModule"/> is high.
        /// </summary>
        /// <remarks>
        /// Implement this event handler and the <see cref="TestModuleLow"/> event handler
        /// when you want to provide an action associated with TestModule activity.
        /// The state of the TestModule is passed to the <see cref="TestModuleEventHandler"/> delegate,
        /// so you can use the same event handler for both TestModule states.
        /// </remarks>
        public event TestModuleEventHandler TestModuleHigh;

        /// <summary>
        /// Raised when the state of <see cref="TestModule"/> is low.
        /// </summary>
        /// <remarks>
        /// Implement this event handler and the <see cref="TestModuleHigh"/> event handler
        /// when you want to provide an action associated with TestModule activity.
        /// Since the state of the TestModule is passed to the <see cref="TestModuleEventHandler"/> delegate,
        /// you can use the same event handler for both TestModule states.
        /// </remarks>
        public event TestModuleEventHandler TestModuleLow;

        private TestModuleEventHandler onTestModule;

        /// <summary>
        /// Raises the <see cref="TestModuleHigh"/> or <see cref="TestModuleLow"/> event.
        /// </summary>
        /// <param name="sender">The <see cref="TestModule"/> that raised the event.</param>
        /// <param name="TestModuleState">The state of the TestModule.</param>
        protected virtual void OnTestModuleEvent(TestModule sender, TestModuleState TestModuleState)
        {
            if (this.onTestModule == null)
            {
                this.onTestModule = new TestModuleEventHandler(this.OnTestModuleEvent);
            }

            if (TestModuleState == TestModule.TestModuleState.High)
            {
                // Program.CheckAndInvoke helps event callers get onto the Dispatcher thread.  
                // If the event is null then it returns false.
                // If it is called while not on the Dispatcher thread, it returns false but also re-invokes this method on the Dispatcher.
                // If on the thread, it returns true so that the caller can execute the event.
                if (Program.CheckAndInvoke(TestModuleHigh, this.onTestModule, sender, TestModuleState))
                {
                    this.TestModuleHigh(sender, TestModuleState);
                }
            }
            else
            {
                if (Program.CheckAndInvoke(TestModuleLow, this.onTestModule, sender, TestModuleState))
                {
                    this.TestModuleLow(sender, TestModuleState);
                }
            }
        }

When you want to raise the event from within the module (in this example, as a result of an interrupt being triggered) you would do so like this:


        private void _input_Interrupt(GTI.InterruptInput input, bool value)
        {
            this.OnTestModuleEvent(this, value ? TestModuleState.Low : TestModuleState.High);
        }


#7

Thanks to all for responses.
I write the questions because into the Seeed drivers their uses always “Program.CheckAndInvoke”, bug we have some problem with event notify.
I needed to clear my head.
@ Nicolas If used your example I have the same problem that the requests are queued to Dispatcher thread.

Thanks
Bye


#8

Hi John,

Apologies for the delay in replying about this - it’s been a busy week.

You’re right - following this pattern means that events will end up in the Dispatcher. This is by design, as it allows users of your module drivers (particularly ones that may unfamiliar with concepts such as threads) to avoid cross-thread invocation problems by making sure everything ends up in a single event queue in the same thread.

These posts might be relevant:


http://www.netmf.com/gadgeteer/forum/default.aspx?g=posts&t=2301

Reading back to your original issue, you say that events are not always received by the handlers when you invoke them. One possibility is may be that there are too many events being generated, and that the dispatcher queue is growing faster than the events can be handled?