InvokeRequired/Invoke on CF 2.0

G

Guest

I know that this is a common problem, but I'm having trouble using Invoke to
cross to the UI thread on a CF 2.0 application. My problem doesn't fit the
typical problem associated with accessing controls though. When my event
fires from the non-UI thread, I check InvokeRequired, and if true, call the
same event again. This time, InvokeRequired should be false and the logic
should execute.

If I call the method from the UI thread (i.e. a button click event)
InvokeRequired is false and all is well. If I call from a non-UI thread (an
Intel Mobile SDK power event) InvokeRequired returns true, I can trace to the
Invoke line, but the debugger never indicates that the method is actually
invoked. Any thoughts?


private void PowerEventHandler(Event e)
{
// Events occur on non-UI thread
if (this.InvokeRequired)
{
this.Invoke(powerChangeObserver.NotifyDelegate, new object[]
{ e });
return;
}

UpdatePowerInfo();
}

private void UpdatePowerInfo()
{
if (myPower.Source.GetValue() == SourceEnum.External)
powerLabel.Text = "AC";
else
powerLabel.Text = "Battery";
}
 
G

Guest

The NotifyDelegate is a delegate property defined as:

public delegate void ObserverNotifyDelegate(Event eEvent);

It refers back to the PowerEventHandler method.

What's the definition of powerChangeObserver.NotifyDelegate?

-Chris


Arian T. Kulp said:
I know that this is a common problem, but I'm having trouble using Invoke
to
cross to the UI thread on a CF 2.0 application. My problem doesn't fit
the
typical problem associated with accessing controls though. When my event
fires from the non-UI thread, I check InvokeRequired, and if true, call
the
same event again. This time, InvokeRequired should be false and the logic
should execute.

If I call the method from the UI thread (i.e. a button click event)
InvokeRequired is false and all is well. If I call from a non-UI thread
(an
Intel Mobile SDK power event) InvokeRequired returns true, I can trace to
the
Invoke line, but the debugger never indicates that the method is actually
invoked. Any thoughts?


private void PowerEventHandler(Event e)
{
// Events occur on non-UI thread
if (this.InvokeRequired)
{
this.Invoke(powerChangeObserver.NotifyDelegate, new
object[]
{ e });
return;
}

UpdatePowerInfo();
}

private void UpdatePowerInfo()
{
if (myPower.Source.GetValue() == SourceEnum.External)
powerLabel.Text = "AC";
else
powerLabel.Text = "Battery";
}
 
G

Guest

Well, I'm confused, but I got it working. I changed from Invoke to
BeginInvoke. I didn't need it to be asynchronous so it didn't occur to me (I
don't think that it was an option pre-2.0 either). I think that I didn't
really make it clear, but using Invoke the application simply locked up after
the call to Invoke. Not only did it not Invoke, but it locked up. Now it
works just fine.

Any idea why? I hate when I get something working but don't know why!
Maybe something else is wrong and this is just a workaround. It seems that
either way should be fine.
 
G

Guest

What you describe sounds like a deadlock situation between your non-UI and UI
threads. My best guess is that somewhere you have the UI thread waiting on an
event or attempting to acquire a lock that is being held by your non-UI
thread. When you call invoke() that non-UI thread can't procede to signal the
event or release the lock until the Invoke() completes. But the Invoke()
can't complete until the UI thread gets whatever lock or event it is waiting
for in some other handler so that it can move on to invoking this delegate.
By using BeginInvoke you allow the non-UI thread to continue, releasing the
lock or signaling the event sometime later, which would then free the UI
thread to continue and execute the invoked delegate. The best way to check
this would be to lock-up the app and then pause and inspect where the UI
thread is in the debugger.

- Noah Falk
..Net Compact Framework

Arian T. Kulp said:
Well, I'm confused, but I got it working. I changed from Invoke to
BeginInvoke. I didn't need it to be asynchronous so it didn't occur to me (I
don't think that it was an option pre-2.0 either). I think that I didn't
really make it clear, but using Invoke the application simply locked up after
the call to Invoke. Not only did it not Invoke, but it locked up. Now it
works just fine.

Any idea why? I hate when I get something working but don't know why!
Maybe something else is wrong and this is just a workaround. It seems that
either way should be fine.

Arian T. Kulp said:
I know that this is a common problem, but I'm having trouble using Invoke to
cross to the UI thread on a CF 2.0 application. My problem doesn't fit the
typical problem associated with accessing controls though. When my event
fires from the non-UI thread, I check InvokeRequired, and if true, call the
same event again. This time, InvokeRequired should be false and the logic
should execute.

If I call the method from the UI thread (i.e. a button click event)
InvokeRequired is false and all is well. If I call from a non-UI thread (an
Intel Mobile SDK power event) InvokeRequired returns true, I can trace to the
Invoke line, but the debugger never indicates that the method is actually
invoked. Any thoughts?


private void PowerEventHandler(Event e)
{
// Events occur on non-UI thread
if (this.InvokeRequired)
{
this.Invoke(powerChangeObserver.NotifyDelegate, new object[]
{ e });
return;
}

UpdatePowerInfo();
}

private void UpdatePowerInfo()
{
if (myPower.Source.GetValue() == SourceEnum.External)
powerLabel.Text = "AC";
else
powerLabel.Text = "Battery";
}
 
G

Guest

I agree that it looks like a classic case of deadlock, but I can't, for the
life of me, figure out where it would be. It's a very simplistic
application, really just a demo of the features. No locks, synchronized
blocks, mutexes, monitors, etc. Oh well, the biggest thing is getting it to
work at all! Thanks for the response.

Noah Falk - MSFT said:
What you describe sounds like a deadlock situation between your non-UI and UI
threads. My best guess is that somewhere you have the UI thread waiting on an
event or attempting to acquire a lock that is being held by your non-UI
thread. When you call invoke() that non-UI thread can't procede to signal the
event or release the lock until the Invoke() completes. But the Invoke()
can't complete until the UI thread gets whatever lock or event it is waiting
for in some other handler so that it can move on to invoking this delegate.
By using BeginInvoke you allow the non-UI thread to continue, releasing the
lock or signaling the event sometime later, which would then free the UI
thread to continue and execute the invoked delegate. The best way to check
this would be to lock-up the app and then pause and inspect where the UI
thread is in the debugger.

- Noah Falk
.Net Compact Framework

Arian T. Kulp said:
Well, I'm confused, but I got it working. I changed from Invoke to
BeginInvoke. I didn't need it to be asynchronous so it didn't occur to me (I
don't think that it was an option pre-2.0 either). I think that I didn't
really make it clear, but using Invoke the application simply locked up after
the call to Invoke. Not only did it not Invoke, but it locked up. Now it
works just fine.

Any idea why? I hate when I get something working but don't know why!
Maybe something else is wrong and this is just a workaround. It seems that
either way should be fine.

Arian T. Kulp said:
I know that this is a common problem, but I'm having trouble using Invoke to
cross to the UI thread on a CF 2.0 application. My problem doesn't fit the
typical problem associated with accessing controls though. When my event
fires from the non-UI thread, I check InvokeRequired, and if true, call the
same event again. This time, InvokeRequired should be false and the logic
should execute.

If I call the method from the UI thread (i.e. a button click event)
InvokeRequired is false and all is well. If I call from a non-UI thread (an
Intel Mobile SDK power event) InvokeRequired returns true, I can trace to the
Invoke line, but the debugger never indicates that the method is actually
invoked. Any thoughts?


private void PowerEventHandler(Event e)
{
// Events occur on non-UI thread
if (this.InvokeRequired)
{
this.Invoke(powerChangeObserver.NotifyDelegate, new object[]
{ e });
return;
}

UpdatePowerInfo();
}

private void UpdatePowerInfo()
{
if (myPower.Source.GetValue() == SourceEnum.External)
powerLabel.Text = "AC";
else
powerLabel.Text = "Battery";
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top