Asychronous events and rendering contexts

R

Roger Crawfis

Hopefully this is the right newsgroup. I figured you guys would be the best
experts on this.

I am learning C# and .NET and went a little crazy with the events. Now I am
not sure how to isolate this problem. Here is my architecture, I have:
1. an OpenGLPanel class derived from UserControl that handles the repainting
using OpenGL. A render event is published for subscribers to paint into the
window.
2. a Manipulator class that handles mouse and keyboard events to cause
rotations, scales, etc. using events.
3. a Camera class that rotates, zooms, etc. based on any subscriptions to a
Manipulator and posts view update events.

Okay, simple scenario, I have a form with two OpenGLPanels, visible. Each
has a camera and listens for the camera events. The camera listen for the
manipulator events. The manipulator listen's for the form's mouse and
keyboard events (a complete cycle!!!!!). The main form has a method to draw
an object and subscribes to the OpenGLPanel's render event.

Things work great in a serial world. I even could attach a manipulator to
both cameras, etc. Pretty cool!! I was just started to really like this new
environment. I decided to switch from just firing the event to doing an
asynchronous call (as a first step to remoting the camera). I would really
like a OneWay approach for the camera, but both of these destroy the OpenGL
context or something. Right now, I am only processing the camera updates to
the OpenGLPanel's asynchronously, but would suspect that all of the mouse
events are also handles asynchronously. The render events will always be
sequential, but I would also like to have the manipulator events happen
OneWay to the cameras.

The problem with the render made sense to me at first, if I set the active
rendering context and then the thread got bumped, etc. I added
[Synchronization] in front of the OpenGLPanel class. It and the Form1 class
are the only ones that make OpenGL calls. I get one of the Panels not
redrawing. The calls are all happening, but I think something in the state
got messed up. The other panel starts off blank and then when I force a
particular event (set of events) it shows up and works properly. Changing
the subscription order seems to reverse which panel works and which one does
not. Pretty much every method is atomic and nothing is left in a bad state
(if I programmed it correctly). I decided to add [Synchronization] before
all of my classes, but nothing helps. BTW, I never create any threads, just
those (two) from a default Windows form. I am running on a single CPU
machine.

Okay, now for the question(s):
1) Is this a correct way to protect a shared system resource?
2) Is there a better way?
3) Any guesses on what might be going on before I attempt to boil the code
down to a simpler test case (or assugn it as a midterm question :) )?
4) I can see the High priority thread preempting the other thread, such that
mouse calls are continually triggered before any updates to the display can
finish. I would expect, that after I release the mouse and wait idle for
awhile the display would redraw.


Some other questions on multi-tasking:
4) My counter indicates I am still getting 70-90 frames-per-second, but
visually, it is more like 1-2 fps.
5) Are the events queued, or do I always just get the most recent event? If
they are queued, is there an easy way to only get the latest. I want to
display with the latest camera, not march thru all of the events.
6) How does a Windows form split up its tasks into threads? I know you want
the user interface thread to be at a high priority, is everything in the
form then issued at a low priority? This would include control updates and
displays, so ...

This is all educational code for my own amusement, so I happy to give the
entire project to anyone interested in looking into this further.

Roger Crawfis
Associate Professor
Computer Science and Engineering Dept.
The Ohio State University
 
K

Ken Kolda

See comments inline below...


Roger Crawfis said:
Hopefully this is the right newsgroup. I figured you guys would be the
best
experts on this.

I am learning C# and .NET and went a little crazy with the events. Now I
am
not sure how to isolate this problem. Here is my architecture, I have:
1. an OpenGLPanel class derived from UserControl that handles the
repainting
using OpenGL. A render event is published for subscribers to paint into
the
window.
2. a Manipulator class that handles mouse and keyboard events to cause
rotations, scales, etc. using events.
3. a Camera class that rotates, zooms, etc. based on any subscriptions to
a
Manipulator and posts view update events.

Okay, simple scenario, I have a form with two OpenGLPanels, visible. Each
has a camera and listens for the camera events. The camera listen for the
manipulator events. The manipulator listen's for the form's mouse and
keyboard events (a complete cycle!!!!!). The main form has a method to
draw
an object and subscribes to the OpenGLPanel's render event.

Things work great in a serial world. I even could attach a manipulator to
both cameras, etc. Pretty cool!! I was just started to really like this
new
environment. I decided to switch from just firing the event to doing an
asynchronous call (as a first step to remoting the camera). I would really
like a OneWay approach for the camera, but both of these destroy the
OpenGL
context or something. Right now, I am only processing the camera updates
to
the OpenGLPanel's asynchronously, but would suspect that all of the mouse
events are also handles asynchronously. The render events will always be
sequential, but I would also like to have the manipulator events happen
OneWay to the cameras.

The problem with the render made sense to me at first, if I set the active
rendering context and then the thread got bumped, etc. I added
[Synchronization] in front of the OpenGLPanel class. It and the Form1
class
are the only ones that make OpenGL calls. I get one of the Panels not
redrawing. The calls are all happening, but I think something in the state
got messed up. The other panel starts off blank and then when I force a
particular event (set of events) it shows up and works properly. Changing
the subscription order seems to reverse which panel works and which one
does
not. Pretty much every method is atomic and nothing is left in a bad state
(if I programmed it correctly). I decided to add [Synchronization] before
all of my classes, but nothing helps. BTW, I never create any threads,
just
those (two) from a default Windows form. I am running on a single CPU
machine.

Okay, now for the question(s):
1) Is this a correct way to protect a shared system resource?

I'm not sure why you're using the [Synchronization] attribute -- are you
using COM+ for some part of your implementation? Or do you mean that you're
using the [MethodImpl(MethodImplOption.Synchronized)]? I don't know anything
about OpenGL or what issues may be inherent in using it, however, there are
issues to be aware of when using async events with Windows Forms.

First is that event form has a UI thread on which all UI-based events must
be handled. This includes events that paint the user interface. So, if
you're painting on the UI from a thread you spawned by invoking an event
asynchronously, you will likely run into problems (and they're usually odd
behaviors as opposed to the UI crashing). Look into the Form.Invoke() method
for info on marshalling the calls back to the UI thread.

Also, you asked about whether mouse events happen asynchronously -- the
answer is No. Mouse events happen on the UI thread just like any other event
which comes to your window via the Windows message pump.
2) Is there a better way?

If you're just looking to make sure access to a data element is thread-safe,
use the lock() statement (in C#) to accomplish this. Locking creates
critical sections to prevent concurrent use of shared resources.
3) Any guesses on what might be going on before I attempt to boil the code
down to a simpler test case (or assugn it as a midterm question :) )?

Besides what I've mentioned before, no. I don't know enough about OpenGL to
know. If you can post a simply code sample, that could help in diagnosing
the problem.
4) I can see the High priority thread preempting the other thread, such
that
mouse calls are continually triggered before any updates to the display
can
finish. I would expect, that after I release the mouse and wait idle for
awhile the display would redraw.


Some other questions on multi-tasking:
4) My counter indicates I am still getting 70-90 frames-per-second, but
visually, it is more like 1-2 fps.
5) Are the events queued, or do I always just get the most recent event?
If
they are queued, is there an easy way to only get the latest. I want to
display with the latest camera, not march thru all of the events.

Events are queued, so if you want to optimize to prevent unnecessary
painting, you'll have to do this yourself.
6) How does a Windows form split up its tasks into threads? I know you
want
the user interface thread to be at a high priority, is everything in the
form then issued at a low priority? This would include control updates and
displays, so ...

As mentioned above, all of this is happening on the same thread. You, of
course, can spawn other threads to perform non-UI-related tasks and set the
priority on those thread accordingly.

Regards -
Ken
 
R

Roger Crawfis

Thanks Ken. The "this.Invoke()" was what I needed. I had to reorganize my code somewhat to accomplish this (yet another indirection), since the event publisher is not the Form for some of the events. OneWay now *seems to* work fine. The astericks are there because I am not totally confident it is correct. If I use BeginInvoke and then WaitOne(), it never returns. Below is my EventsHelper for this. It follows Juval Lowy's excellent book on "Programming .NET Components". He did not have any EndInvoke or Wait(). In fact, he states you can not call EndInvoke() when publishing asynchronously (p. 138). Most curious, but I think he means using the EventsHelper class. I really do not care about any return values, but thought I would give any threads a chance to process the events before moving on. A WaitOne(10, false) seems to work fine, but it will wait for 10 msec. Something is wrong in my logic below.

On the [Synchronization] attribute flag does not necessarily mean a COM object if I understand this book correctly. It provides automatic synchronization (locking) at the component level. This would imply to me that once a thread starts a method on a synchronious component, it will block all other threads trying to access it. It seems to work with the OneWay, as the individual methods are not thread safe without it.

Thank you very much for your time. I am trying to track down the .NET remoting issues now, so I may have another question (separate thread though).

EventsHelper.cs
----------[snip]
//

// Asynchronous event firing with exception catching

//

delegate void AsyncFire( Delegate client, object[] args );

public static void FireAsync( Delegate publishedEvent, params object[] args )

{

if( publishedEvent == null )

return;

Delegate[] clientList = publishedEvent.GetInvocationList();

IAsyncResult[] asyncResult = new IAsyncResult[clientList.Length];

AsyncFire asyncClientCall;

int i = 0;

foreach( Delegate sink in clientList )

{

try

{

asyncClientCall = new AsyncFire( InvokeClient );

asyncResult = asyncClientCall.BeginInvoke( sink, args, null, null );

i++;

}

catch{}

}

for( i=0; i < clientList.Length; i++ )

{

try

{

asyncResult.AsyncWaitHandle.WaitOne( 10, false );

}

catch{}

}

}

private static void InvokeClient( Delegate client, object[] args )

{

client.DynamicInvoke( args );

}





Ken Kolda said:
See comments inline below...


Roger Crawfis said:
Hopefully this is the right newsgroup. I figured you guys would be the
best
experts on this.

I am learning C# and .NET and went a little crazy with the events. Now I
am
not sure how to isolate this problem. Here is my architecture, I have:
1. an OpenGLPanel class derived from UserControl that handles the
repainting
using OpenGL. A render event is published for subscribers to paint into
the
window.
2. a Manipulator class that handles mouse and keyboard events to cause
rotations, scales, etc. using events.
3. a Camera class that rotates, zooms, etc. based on any subscriptions to
a
Manipulator and posts view update events.

Okay, simple scenario, I have a form with two OpenGLPanels, visible. Each
has a camera and listens for the camera events. The camera listen for the
manipulator events. The manipulator listen's for the form's mouse and
keyboard events (a complete cycle!!!!!). The main form has a method to
draw
an object and subscribes to the OpenGLPanel's render event.

Things work great in a serial world. I even could attach a manipulator to
both cameras, etc. Pretty cool!! I was just started to really like this
new
environment. I decided to switch from just firing the event to doing an
asynchronous call (as a first step to remoting the camera). I would really
like a OneWay approach for the camera, but both of these destroy the
OpenGL
context or something. Right now, I am only processing the camera updates
to
the OpenGLPanel's asynchronously, but would suspect that all of the mouse
events are also handles asynchronously. The render events will always be
sequential, but I would also like to have the manipulator events happen
OneWay to the cameras.

The problem with the render made sense to me at first, if I set the active
rendering context and then the thread got bumped, etc. I added
[Synchronization] in front of the OpenGLPanel class. It and the Form1
class
are the only ones that make OpenGL calls. I get one of the Panels not
redrawing. The calls are all happening, but I think something in the state
got messed up. The other panel starts off blank and then when I force a
particular event (set of events) it shows up and works properly. Changing
the subscription order seems to reverse which panel works and which one
does
not. Pretty much every method is atomic and nothing is left in a bad state
(if I programmed it correctly). I decided to add [Synchronization] before
all of my classes, but nothing helps. BTW, I never create any threads,
just
those (two) from a default Windows form. I am running on a single CPU
machine.

Okay, now for the question(s):
1) Is this a correct way to protect a shared system resource?

I'm not sure why you're using the [Synchronization] attribute -- are you
using COM+ for some part of your implementation? Or do you mean that you're
using the [MethodImpl(MethodImplOption.Synchronized)]? I don't know anything
about OpenGL or what issues may be inherent in using it, however, there are
issues to be aware of when using async events with Windows Forms.

First is that event form has a UI thread on which all UI-based events must
be handled. This includes events that paint the user interface. So, if
you're painting on the UI from a thread you spawned by invoking an event
asynchronously, you will likely run into problems (and they're usually odd
behaviors as opposed to the UI crashing). Look into the Form.Invoke() method
for info on marshalling the calls back to the UI thread.

Also, you asked about whether mouse events happen asynchronously -- the
answer is No. Mouse events happen on the UI thread just like any other event
which comes to your window via the Windows message pump.
2) Is there a better way?

If you're just looking to make sure access to a data element is thread-safe,
use the lock() statement (in C#) to accomplish this. Locking creates
critical sections to prevent concurrent use of shared resources.
3) Any guesses on what might be going on before I attempt to boil the code
down to a simpler test case (or assugn it as a midterm question :) )?

Besides what I've mentioned before, no. I don't know enough about OpenGL to
know. If you can post a simply code sample, that could help in diagnosing
the problem.
4) I can see the High priority thread preempting the other thread, such
that
mouse calls are continually triggered before any updates to the display
can
finish. I would expect, that after I release the mouse and wait idle for
awhile the display would redraw.


Some other questions on multi-tasking:
4) My counter indicates I am still getting 70-90 frames-per-second, but
visually, it is more like 1-2 fps.
5) Are the events queued, or do I always just get the most recent event?
If
they are queued, is there an easy way to only get the latest. I want to
display with the latest camera, not march thru all of the events.

Events are queued, so if you want to optimize to prevent unnecessary
painting, you'll have to do this yourself.
6) How does a Windows form split up its tasks into threads? I know you
want
the user interface thread to be at a high priority, is everything in the
form then issued at a low priority? This would include control updates and
displays, so ...

As mentioned above, all of this is happening on the same thread. You, of
course, can spawn other threads to perform non-UI-related tasks and set the
priority on those thread accordingly.

Regards -
Ken
 
K

Ken Kolda

The code you have looks good. The fact that WaitOne() doesn't return is odd though. The main reason I could see for this is that your FireAsync() method is being invoked on the UI thread (e.g. in response to a button click on a form) and one (or more) of the delegates being invoked is, in turn, calling Form.Invoke() to marshal the call to the UI thread. This would cause a deadlock condition so the WaitOne() won't return. Or there could be some other thread locking that's not shown in the code below (e.g. via marking a class as syncrhonized).

Ken

Thanks Ken. The "this.Invoke()" was what I needed. I had to reorganize my code somewhat to accomplish this (yet another indirection), since the event publisher is not the Form for some of the events. OneWay now *seems to* work fine. The astericks are there because I am not totally confident it is correct. If I use BeginInvoke and then WaitOne(), it never returns. Below is my EventsHelper for this. It follows Juval Lowy's excellent book on "Programming .NET Components". He did not have any EndInvoke or Wait(). In fact, he states you can not call EndInvoke() when publishing asynchronously (p. 138). Most curious, but I think he means using the EventsHelper class. I really do not care about any return values, but thought I would give any threads a chance to process the events before moving on. A WaitOne(10, false) seems to work fine, but it will wait for 10 msec. Something is wrong in my logic below.

On the [Synchronization] attribute flag does not necessarily mean a COM object if I understand this book correctly. It provides automatic synchronization (locking) at the component level. This would imply to me that once a thread starts a method on a synchronious component, it will block all other threads trying to access it. It seems to work with the OneWay, as the individual methods are not thread safe without it.

Thank you very much for your time. I am trying to track down the .NET remoting issues now, so I may have another question (separate thread though).

EventsHelper.cs
----------[snip]
//

// Asynchronous event firing with exception catching

//

delegate void AsyncFire( Delegate client, object[] args );

public static void FireAsync( Delegate publishedEvent, params object[] args )

{

if( publishedEvent == null )

return;

Delegate[] clientList = publishedEvent.GetInvocationList();

IAsyncResult[] asyncResult = new IAsyncResult[clientList.Length];

AsyncFire asyncClientCall;

int i = 0;

foreach( Delegate sink in clientList )

{

try

{

asyncClientCall = new AsyncFire( InvokeClient );

asyncResult = asyncClientCall.BeginInvoke( sink, args, null, null );

i++;

}

catch{}

}

for( i=0; i < clientList.Length; i++ )

{

try

{

asyncResult.AsyncWaitHandle.WaitOne( 10, false );

}

catch{}

}

}

private static void InvokeClient( Delegate client, object[] args )

{

client.DynamicInvoke( args );

}





Ken Kolda said:
See comments inline below...


Roger Crawfis said:
Hopefully this is the right newsgroup. I figured you guys would be the
best
experts on this.

I am learning C# and .NET and went a little crazy with the events. Now I
am
not sure how to isolate this problem. Here is my architecture, I have:
1. an OpenGLPanel class derived from UserControl that handles the
repainting
using OpenGL. A render event is published for subscribers to paint into
the
window.
2. a Manipulator class that handles mouse and keyboard events to cause
rotations, scales, etc. using events.
3. a Camera class that rotates, zooms, etc. based on any subscriptions to
a
Manipulator and posts view update events.

Okay, simple scenario, I have a form with two OpenGLPanels, visible. Each
has a camera and listens for the camera events. The camera listen for the
manipulator events. The manipulator listen's for the form's mouse and
keyboard events (a complete cycle!!!!!). The main form has a method to
draw
an object and subscribes to the OpenGLPanel's render event.

Things work great in a serial world. I even could attach a manipulator to
both cameras, etc. Pretty cool!! I was just started to really like this
new
environment. I decided to switch from just firing the event to doing an
asynchronous call (as a first step to remoting the camera). I would really
like a OneWay approach for the camera, but both of these destroy the
OpenGL
context or something. Right now, I am only processing the camera updates
to
the OpenGLPanel's asynchronously, but would suspect that all of the mouse
events are also handles asynchronously. The render events will always be
sequential, but I would also like to have the manipulator events happen
OneWay to the cameras.

The problem with the render made sense to me at first, if I set the active
rendering context and then the thread got bumped, etc. I added
[Synchronization] in front of the OpenGLPanel class. It and the Form1
class
are the only ones that make OpenGL calls. I get one of the Panels not
redrawing. The calls are all happening, but I think something in the state
got messed up. The other panel starts off blank and then when I force a
particular event (set of events) it shows up and works properly. Changing
the subscription order seems to reverse which panel works and which one
does
not. Pretty much every method is atomic and nothing is left in a bad state
(if I programmed it correctly). I decided to add [Synchronization] before
all of my classes, but nothing helps. BTW, I never create any threads,
just
those (two) from a default Windows form. I am running on a single CPU
machine.

Okay, now for the question(s):
1) Is this a correct way to protect a shared system resource?

I'm not sure why you're using the [Synchronization] attribute -- are you
using COM+ for some part of your implementation? Or do you mean that you're
using the [MethodImpl(MethodImplOption.Synchronized)]? I don't know anything
about OpenGL or what issues may be inherent in using it, however, there are
issues to be aware of when using async events with Windows Forms.

First is that event form has a UI thread on which all UI-based events must
be handled. This includes events that paint the user interface. So, if
you're painting on the UI from a thread you spawned by invoking an event
asynchronously, you will likely run into problems (and they're usually odd
behaviors as opposed to the UI crashing). Look into the Form.Invoke() method
for info on marshalling the calls back to the UI thread.

Also, you asked about whether mouse events happen asynchronously -- the
answer is No. Mouse events happen on the UI thread just like any other event
which comes to your window via the Windows message pump.
2) Is there a better way?

If you're just looking to make sure access to a data element is thread-safe,
use the lock() statement (in C#) to accomplish this. Locking creates
critical sections to prevent concurrent use of shared resources.
3) Any guesses on what might be going on before I attempt to boil the code
down to a simpler test case (or assugn it as a midterm question :) )?

Besides what I've mentioned before, no. I don't know enough about OpenGL to
know. If you can post a simply code sample, that could help in diagnosing
the problem.
4) I can see the High priority thread preempting the other thread, such
that
mouse calls are continually triggered before any updates to the display
can
finish. I would expect, that after I release the mouse and wait idle for
awhile the display would redraw.


Some other questions on multi-tasking:
4) My counter indicates I am still getting 70-90 frames-per-second, but
visually, it is more like 1-2 fps.
5) Are the events queued, or do I always just get the most recent event?
If
they are queued, is there an easy way to only get the latest. I want to
display with the latest camera, not march thru all of the events.

Events are queued, so if you want to optimize to prevent unnecessary
painting, you'll have to do this yourself.
6) How does a Windows form split up its tasks into threads? I know you
want
the user interface thread to be at a high priority, is everything in the
form then issued at a low priority? This would include control updates and
displays, so ...

As mentioned above, all of this is happening on the same thread. You, of
course, can spawn other threads to perform non-UI-related tasks and set the
priority on those thread accordingly.

Regards -
Ken
 
R

Roger Crawfis

Ken,

Thanks for your quick reply. You are right on. The UI Thread is calling the WaitOne() and is stopped for that, while we try to tell it to handle the event. Classic deadlock. Thanks.

Roger
The code you have looks good. The fact that WaitOne() doesn't return is odd though. The main reason I could see for this is that your FireAsync() method is being invoked on the UI thread (e.g. in response to a button click on a form) and one (or more) of the delegates being invoked is, in turn, calling Form.Invoke() to marshal the call to the UI thread. This would cause a deadlock condition so the WaitOne() won't return. Or there could be some other thread locking that's not shown in the code below (e.g. via marking a class as syncrhonized).

Ken
 
R

Roger Crawfis

There is one small additional problem. I also had some keyboard controls. I use say the numpad 6 to rotate right. If the Shift key is held down it rotates at a faster speed, if the control is held down it provides some fine control. With the asynchronous events the control key no longer works. I suppose I have to marshal this to the UI thread as well. Is there an easier way though? I can not find anything in the sender (cast to a Control) that will help. It seems like I should have all of the information needed already. Any ideas, or do I need to use the UI thread?

I guess while we are at it, is there any way to get the modifiers for the Keypress event? Seems rather silly that I need three separate events for the alphanumeric keys, the arrow keys, and the numpad.

Roger
Thanks Ken. The "this.Invoke()" was what I needed. I had to reorganize my code somewhat to accomplish this (yet another indirection), since the event publisher is not the Form for some of the events. OneWay now *seems to* work fine. The astericks are there because I am not totally confident it is correct. If I use BeginInvoke and then WaitOne(), it never returns. Below is my EventsHelper for this. It follows Juval Lowy's excellent book on "Programming .NET Components". He did not have any EndInvoke or Wait(). In fact, he states you can not call EndInvoke() when publishing asynchronously (p. 138). Most curious, but I think he means using the EventsHelper class. I really do not care about any return values, but thought I would give any threads a chance to process the events before moving on. A WaitOne(10, false) seems to work fine, but it will wait for 10 msec. Something is wrong in my logic below.

On the [Synchronization] attribute flag does not necessarily mean a COM object if I understand this book correctly. It provides automatic synchronization (locking) at the component level. This would imply to me that once a thread starts a method on a synchronious component, it will block all other threads trying to access it. It seems to work with the OneWay, as the individual methods are not thread safe without it.

Thank you very much for your time. I am trying to track down the .NET remoting issues now, so I may have another question (separate thread though).

EventsHelper.cs
----------[snip]
//

// Asynchronous event firing with exception catching

//

delegate void AsyncFire( Delegate client, object[] args );

public static void FireAsync( Delegate publishedEvent, params object[] args )

{

if( publishedEvent == null )

return;

Delegate[] clientList = publishedEvent.GetInvocationList();

IAsyncResult[] asyncResult = new IAsyncResult[clientList.Length];

AsyncFire asyncClientCall;

int i = 0;

foreach( Delegate sink in clientList )

{

try

{

asyncClientCall = new AsyncFire( InvokeClient );

asyncResult = asyncClientCall.BeginInvoke( sink, args, null, null );

i++;

}

catch{}

}

for( i=0; i < clientList.Length; i++ )

{

try

{

asyncResult.AsyncWaitHandle.WaitOne( 10, false );

}

catch{}

}

}

private static void InvokeClient( Delegate client, object[] args )

{

client.DynamicInvoke( args );

}





Ken Kolda said:
See comments inline below...


Roger Crawfis said:
Hopefully this is the right newsgroup. I figured you guys would be the
best
experts on this.

I am learning C# and .NET and went a little crazy with the events. Now I
am
not sure how to isolate this problem. Here is my architecture, I have:
1. an OpenGLPanel class derived from UserControl that handles the
repainting
using OpenGL. A render event is published for subscribers to paint into
the
window.
2. a Manipulator class that handles mouse and keyboard events to cause
rotations, scales, etc. using events.
3. a Camera class that rotates, zooms, etc. based on any subscriptions to
a
Manipulator and posts view update events.

Okay, simple scenario, I have a form with two OpenGLPanels, visible. Each
has a camera and listens for the camera events. The camera listen for the
manipulator events. The manipulator listen's for the form's mouse and
keyboard events (a complete cycle!!!!!). The main form has a method to
draw
an object and subscribes to the OpenGLPanel's render event.

Things work great in a serial world. I even could attach a manipulator to
both cameras, etc. Pretty cool!! I was just started to really like this
new
environment. I decided to switch from just firing the event to doing an
asynchronous call (as a first step to remoting the camera). I would really
like a OneWay approach for the camera, but both of these destroy the
OpenGL
context or something. Right now, I am only processing the camera updates
to
the OpenGLPanel's asynchronously, but would suspect that all of the mouse
events are also handles asynchronously. The render events will always be
sequential, but I would also like to have the manipulator events happen
OneWay to the cameras.

The problem with the render made sense to me at first, if I set the active
rendering context and then the thread got bumped, etc. I added
[Synchronization] in front of the OpenGLPanel class. It and the Form1
class
are the only ones that make OpenGL calls. I get one of the Panels not
redrawing. The calls are all happening, but I think something in the state
got messed up. The other panel starts off blank and then when I force a
particular event (set of events) it shows up and works properly. Changing
the subscription order seems to reverse which panel works and which one
does
not. Pretty much every method is atomic and nothing is left in a bad state
(if I programmed it correctly). I decided to add [Synchronization] before
all of my classes, but nothing helps. BTW, I never create any threads,
just
those (two) from a default Windows form. I am running on a single CPU
machine.

Okay, now for the question(s):
1) Is this a correct way to protect a shared system resource?

I'm not sure why you're using the [Synchronization] attribute -- are you
using COM+ for some part of your implementation? Or do you mean that you're
using the [MethodImpl(MethodImplOption.Synchronized)]? I don't know anything
about OpenGL or what issues may be inherent in using it, however, there are
issues to be aware of when using async events with Windows Forms.

First is that event form has a UI thread on which all UI-based events must
be handled. This includes events that paint the user interface. So, if
you're painting on the UI from a thread you spawned by invoking an event
asynchronously, you will likely run into problems (and they're usually odd
behaviors as opposed to the UI crashing). Look into the Form.Invoke() method
for info on marshalling the calls back to the UI thread.

Also, you asked about whether mouse events happen asynchronously -- the
answer is No. Mouse events happen on the UI thread just like any other event
which comes to your window via the Windows message pump.
2) Is there a better way?

If you're just looking to make sure access to a data element is thread-safe,
use the lock() statement (in C#) to accomplish this. Locking creates
critical sections to prevent concurrent use of shared resources.
3) Any guesses on what might be going on before I attempt to boil the code
down to a simpler test case (or assugn it as a midterm question :) )?

Besides what I've mentioned before, no. I don't know enough about OpenGL to
know. If you can post a simply code sample, that could help in diagnosing
the problem.
4) I can see the High priority thread preempting the other thread, such
that
mouse calls are continually triggered before any updates to the display
can
finish. I would expect, that after I release the mouse and wait idle for
awhile the display would redraw.


Some other questions on multi-tasking:
4) My counter indicates I am still getting 70-90 frames-per-second, but
visually, it is more like 1-2 fps.
5) Are the events queued, or do I always just get the most recent event?
If
they are queued, is there an easy way to only get the latest. I want to
display with the latest camera, not march thru all of the events.

Events are queued, so if you want to optimize to prevent unnecessary
painting, you'll have to do this yourself.
6) How does a Windows form split up its tasks into threads? I know you
want
the user interface thread to be at a high priority, is everything in the
form then issued at a low priority? This would include control updates and
displays, so ...

As mentioned above, all of this is happening on the same thread. You, of
course, can spawn other threads to perform non-UI-related tasks and set the
priority on those thread accordingly.

Regards -
Ken
 
K

Ken Kolda

Have you looked at the KeyDown event -- it provides all the info with regards to the Alt, Ctrl, Shift keys, etc.

Ken


There is one small additional problem. I also had some keyboard controls. I use say the numpad 6 to rotate right. If the Shift key is held down it rotates at a faster speed, if the control is held down it provides some fine control. With the asynchronous events the control key no longer works. I suppose I have to marshal this to the UI thread as well. Is there an easier way though? I can not find anything in the sender (cast to a Control) that will help. It seems like I should have all of the information needed already. Any ideas, or do I need to use the UI thread?

I guess while we are at it, is there any way to get the modifiers for the Keypress event? Seems rather silly that I need three separate events for the alphanumeric keys, the arrow keys, and the numpad.

Roger
Thanks Ken. The "this.Invoke()" was what I needed. I had to reorganize my code somewhat to accomplish this (yet another indirection), since the event publisher is not the Form for some of the events. OneWay now *seems to* work fine. The astericks are there because I am not totally confident it is correct. If I use BeginInvoke and then WaitOne(), it never returns. Below is my EventsHelper for this. It follows Juval Lowy's excellent book on "Programming .NET Components". He did not have any EndInvoke or Wait(). In fact, he states you can not call EndInvoke() when publishing asynchronously (p. 138). Most curious, but I think he means using the EventsHelper class. I really do not care about any return values, but thought I would give any threads a chance to process the events before moving on. A WaitOne(10, false) seems to work fine, but it will wait for 10 msec. Something is wrong in my logic below.

On the [Synchronization] attribute flag does not necessarily mean a COM object if I understand this book correctly. It provides automatic synchronization (locking) at the component level. This would imply to me that once a thread starts a method on a synchronious component, it will block all other threads trying to access it. It seems to work with the OneWay, as the individual methods are not thread safe without it.

Thank you very much for your time. I am trying to track down the ..NET remoting issues now, so I may have another question (separate thread though).

EventsHelper.cs
----------[snip]
//

// Asynchronous event firing with exception catching

//

delegate void AsyncFire( Delegate client, object[] args );

public static void FireAsync( Delegate publishedEvent, params object[] args )

{

if( publishedEvent == null )

return;

Delegate[] clientList = publishedEvent.GetInvocationList();

IAsyncResult[] asyncResult = new IAsyncResult[clientList.Length];

AsyncFire asyncClientCall;

int i = 0;

foreach( Delegate sink in clientList )

{

try

{

asyncClientCall = new AsyncFire( InvokeClient );

asyncResult = asyncClientCall.BeginInvoke( sink, args, null, null );

i++;

}

catch{}

}

for( i=0; i < clientList.Length; i++ )

{

try

{

asyncResult.AsyncWaitHandle.WaitOne( 10, false );

}

catch{}

}

}

private static void InvokeClient( Delegate client, object[] args )

{

client.DynamicInvoke( args );

}





Ken Kolda said:
See comments inline below...


Roger Crawfis said:
Hopefully this is the right newsgroup. I figured you guys would be the
best
experts on this.

I am learning C# and .NET and went a little crazy with the events. Now I
am
not sure how to isolate this problem. Here is my architecture, I have:
1. an OpenGLPanel class derived from UserControl that handles the
repainting
using OpenGL. A render event is published for subscribers to paint into
the
window.
2. a Manipulator class that handles mouse and keyboard events to cause
rotations, scales, etc. using events.
3. a Camera class that rotates, zooms, etc. based on any subscriptions to
a
Manipulator and posts view update events.

Okay, simple scenario, I have a form with two OpenGLPanels, visible. Each
has a camera and listens for the camera events. The camera listen for the
manipulator events. The manipulator listen's for the form's mouse and
keyboard events (a complete cycle!!!!!). The main form has a method to
draw
an object and subscribes to the OpenGLPanel's render event.

Things work great in a serial world. I even could attach a manipulator to
both cameras, etc. Pretty cool!! I was just started to really like this
new
environment. I decided to switch from just firing the event to doing an
asynchronous call (as a first step to remoting the camera). I would really
like a OneWay approach for the camera, but both of these destroy the
OpenGL
context or something. Right now, I am only processing the camera updates
to
the OpenGLPanel's asynchronously, but would suspect that all of the mouse
events are also handles asynchronously. The render events will always be
sequential, but I would also like to have the manipulator events happen
OneWay to the cameras.

The problem with the render made sense to me at first, if I set the active
rendering context and then the thread got bumped, etc. I added
[Synchronization] in front of the OpenGLPanel class. It and the Form1
class
are the only ones that make OpenGL calls. I get one of the Panels not
redrawing. The calls are all happening, but I think something in the state
got messed up. The other panel starts off blank and then when I force a
particular event (set of events) it shows up and works properly. Changing
the subscription order seems to reverse which panel works and which one
does
not. Pretty much every method is atomic and nothing is left in a bad state
(if I programmed it correctly). I decided to add [Synchronization] before
all of my classes, but nothing helps. BTW, I never create any threads,
just
those (two) from a default Windows form. I am running on a single CPU
machine.

Okay, now for the question(s):
1) Is this a correct way to protect a shared system resource?

I'm not sure why you're using the [Synchronization] attribute -- are you
using COM+ for some part of your implementation? Or do you mean that you're
using the [MethodImpl(MethodImplOption.Synchronized)]? I don't know anything
about OpenGL or what issues may be inherent in using it, however, there are
issues to be aware of when using async events with Windows Forms.

First is that event form has a UI thread on which all UI-based events must
be handled. This includes events that paint the user interface. So, if
you're painting on the UI from a thread you spawned by invoking an event
asynchronously, you will likely run into problems (and they're usually odd
behaviors as opposed to the UI crashing). Look into the Form.Invoke() method
for info on marshalling the calls back to the UI thread.

Also, you asked about whether mouse events happen asynchronously -- the
answer is No. Mouse events happen on the UI thread just like any other event
which comes to your window via the Windows message pump.
2) Is there a better way?

If you're just looking to make sure access to a data element is thread-safe,
use the lock() statement (in C#) to accomplish this. Locking creates
critical sections to prevent concurrent use of shared resources.
3) Any guesses on what might be going on before I attempt to boil the code
down to a simpler test case (or assugn it as a midterm question :) )?

Besides what I've mentioned before, no. I don't know enough about OpenGL to
know. If you can post a simply code sample, that could help in diagnosing
the problem.
4) I can see the High priority thread preempting the other thread, such
that
mouse calls are continually triggered before any updates to the display
can
finish. I would expect, that after I release the mouse and wait idle for
awhile the display would redraw.


Some other questions on multi-tasking:
4) My counter indicates I am still getting 70-90 frames-per-second, but
visually, it is more like 1-2 fps.
5) Are the events queued, or do I always just get the most recent event?
If
they are queued, is there an easy way to only get the latest. I want to
display with the latest camera, not march thru all of the events.

Events are queued, so if you want to optimize to prevent unnecessary
painting, you'll have to do this yourself.
6) How does a Windows form split up its tasks into threads? I know you
want
the user interface thread to be at a high priority, is everything in the
form then issued at a low priority? This would include control updates and
displays, so ...

As mentioned above, all of this is happening on the same thread. You, of
course, can spawn other threads to perform non-UI-related tasks and set the
priority on those thread accordingly.

Regards -
Ken
 

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