SensorInput event stops firing?
Moderator: Moderators
SensorInput event stops firing?
I'm trying to write a very simple .NET (C#) test application to receive an interpret data from a SpaceNavigator PE. After downloading the SDK, it seemed like using the TDxInput.dll COM library would be the easiest way to get up and running, so I set up my test app (registering an event handler for the device's Sensor.SensorInput event), built it, and gave it a run, and guess what? It worked just as I expected it would!! ... that was, until somewhere around 50 SensorInput events had fired, and then it seemed the event would never fire again.
I've re-tested this repeatedly, but the results are roughly the same every time. The number of times that my event handler is called (for the SensorInput event) varies -- it's usually somewhere around 50 or 60 times and sometimes over 200 -- but it always stops working after receiving a small number of reports.
Also, I don't know if there's anything special about how event handlers work under COM, but I've noticed that after I call Connect and subscribe to the event, I can always register additional event handlers without any ill effect, but after the events stop firing, if I attempt to register another event handler, I get a NullReferenceException having the following stack trace:
at System.Runtime.InteropServices.ComTypes.IConnectionPoint.Advise(Object pUnkSink, Int32& pdwCookie)
at TDxInput._ISensorEvents_EventProvider.add_SensorInput(_ISensorEvents_SensorInputEventHandler )
at TDxInput.SensorClass.add_SensorInput(_ISensorEvents_SensorInputEventHandler )
at TDxTests.Form1.btnTestConnection_Click(Object sender, EventArgs e)
[snip]
Does anyone have any idea what might be going on here? In all other respects, the device appears to be working flawlessly.
My system configuration is as follows:
Windows Vista Enterprise (64-bit)
Visual Studio 2005 SP1
(can't think of any other significant variables)
Any help would be much appreciated! Thanks.
(If I can't get this working, then my next step will be to read the input data from the corresponding HID device handle. Having done something like that in the past, I don't imagine this would be too complicated.)
I've re-tested this repeatedly, but the results are roughly the same every time. The number of times that my event handler is called (for the SensorInput event) varies -- it's usually somewhere around 50 or 60 times and sometimes over 200 -- but it always stops working after receiving a small number of reports.
Also, I don't know if there's anything special about how event handlers work under COM, but I've noticed that after I call Connect and subscribe to the event, I can always register additional event handlers without any ill effect, but after the events stop firing, if I attempt to register another event handler, I get a NullReferenceException having the following stack trace:
at System.Runtime.InteropServices.ComTypes.IConnectionPoint.Advise(Object pUnkSink, Int32& pdwCookie)
at TDxInput._ISensorEvents_EventProvider.add_SensorInput(_ISensorEvents_SensorInputEventHandler )
at TDxInput.SensorClass.add_SensorInput(_ISensorEvents_SensorInputEventHandler )
at TDxTests.Form1.btnTestConnection_Click(Object sender, EventArgs e)
[snip]
Does anyone have any idea what might be going on here? In all other respects, the device appears to be working flawlessly.
My system configuration is as follows:
Windows Vista Enterprise (64-bit)
Visual Studio 2005 SP1
(can't think of any other significant variables)
Any help would be much appreciated! Thanks.
(If I can't get this working, then my next step will be to read the input data from the corresponding HID device handle. Having done something like that in the past, I don't imagine this would be too complicated.)
Re: SensorInput event stops firing?
Could you please send up the project so that we can have a look at what is happening?porcus wrote:I'm trying to write a very simple .NET (C#) test application
We havn't encountered this before: the xna and vb samples on the web-site do not display this behavior
Markus
Re: SensorInput event stops firing?
Hi porcus,
If you'd like to send us a project, please contact mbonk or myself on a private message.
Or -- perhaps preferably -- a stripped down project with just the bits that are needed to check the problem up.mbonk wrote:Could you please send up the project so that we can have a look at what is happening?porcus wrote:I'm trying to write a very simple .NET (C#) test application
If you'd like to send us a project, please contact mbonk or myself on a private message.
Nuno Gomes
Hi guys,
Please do NOT jump off to private message stream on this.
I have been banging my head on the same issue for the last week.
My objective is to enable our 6 million line enterprise application to appreciate 3DConnection input, but the event stream quickly stops if at all starting.
I am currently trying to create a mini-project that consistently shows the problem. I have a question in that regard:
[b]Is the TDxInput.Device designed so that several instances can coexist within the same process?[/b]
The API indicates that multiple instances are allowed, but in my mini-project, the event stream will only start from the first instance. I wander if that can be the reason why I have problems with my enterprise project since I am also using Open Inventor from Mercury that has its own interface to 3DConnectioin devices.
Kind regards,
Erik
Please do NOT jump off to private message stream on this.
I have been banging my head on the same issue for the last week.
My objective is to enable our 6 million line enterprise application to appreciate 3DConnection input, but the event stream quickly stops if at all starting.
I am currently trying to create a mini-project that consistently shows the problem. I have a question in that regard:
[b]Is the TDxInput.Device designed so that several instances can coexist within the same process?[/b]
The API indicates that multiple instances are allowed, but in my mini-project, the event stream will only start from the first instance. I wander if that can be the reason why I have problems with my enterprise project since I am also using Open Inventor from Mercury that has its own interface to 3DConnectioin devices.
Kind regards,
Erik
Ok, I think I understand what is going on.
The TDxInput API exposes the TDxInput.Sensor as an attribute of a TDxInput.Device instance. One would think that the sensor should be accessed by rules that conforms to the attribute idiom - that is wrong.
Despite the attribute signature, the interface behaves like a factory! This means that the returned TDxInput.Sensor instance has to be referenced (cached) by the application for as long as it is going to be used.
This was the root of my problems. Reading the description from porcus earlier in this thread, I suspect that he is not caching the TDxInput.Sensor instance.
Somebody more knowledgeable than me may tell if this non-conformant behavior is due to an artifact of the Interop system from Microsoft or an artifact of the TDxInput COM module.
Anyway, it should be worth stating this behavior explicitly in the TDxInput API documentation.
Kind regards,
Erik
The TDxInput API exposes the TDxInput.Sensor as an attribute of a TDxInput.Device instance. One would think that the sensor should be accessed by rules that conforms to the attribute idiom - that is wrong.
Despite the attribute signature, the interface behaves like a factory! This means that the returned TDxInput.Sensor instance has to be referenced (cached) by the application for as long as it is going to be used.
This was the root of my problems. Reading the description from porcus earlier in this thread, I suspect that he is not caching the TDxInput.Sensor instance.
Somebody more knowledgeable than me may tell if this non-conformant behavior is due to an artifact of the Interop system from Microsoft or an artifact of the TDxInput COM module.
Anyway, it should be worth stating this behavior explicitly in the TDxInput API documentation.
Kind regards,
Erik
This is not how the TDxInput API has been designed. Using the Sensor() method of the TDxInput.Device instance will return the TDxInput.Sensor instance belonging to that device.ebaklund wrote:Ok, I think I understand what is going on.
The TDxInput API exposes the TDxInput.Sensor as an attribute of a TDxInput.Device instance. One would think that the sensor should be accessed by rules that conforms to the attribute idiom - that is wrong.
Despite the attribute signature, the interface behaves like a factory! This means that the returned TDxInput.Sensor instance has to be referenced (cached) by the application for as long as it is going to be used.
Thus is is not necessary to keep a reference to the Sensor. It is however necessary to keep a reference to at least one of Device, Keyboard or Sensor for the duration of the connection to the device.
It is highly recommended to only create one instance of the device per application as the cuurent implementation of the system driver does not broadcast the device data to all instances of the TDxInput.Device.
Are you keeping a reference to the device object or why are you creating new instances of the Sensot object?
Markus
Hi,
Thanks for replying.
Kind regards,
Erik
Thanks for replying.
That makes sense from a design point of view and also follows the conventions of the attribute idiom.This is not how the TDxInput API has been designed. Using the Sensor() method of the TDxInput.Device instance will return the TDxInput.Sensor instance belonging to that device.
Yes it is. That is where the problem is. I am using the TDx.TDxInput .NET interface through C#. Without keeping a reference to the Sensor, the lifespan of the Sensor is undetermined and the event stream will die as soon the garbage collector kicks in. Maybe the sensor COM object is kept alive, but how does the Interop system work? It would be nice tho have an Interop expert to shed a light on this.Thus is is not necessary to keep a reference to the Sensor.
Hm.. I think I can live with that. The reason I am slightly worried is because my component coexists in an application where the Open Inventor API from TGS is being used. The Open Inventor library has its own interface to 3DConnection devices, but I guess it is less likely that the library on its own is going to create a 3D Connection device unless explicitly being told to.It is highly recommended to only create one instance of the device per application as the cuurent implementation of the system driver does not broadcast the device data to all instances of the TDxInput.Device.
I construct and keep a reference to the Device around for the whole life cycle of the application. I do NOT construct instances of the Sensor class. I only use the sensor reference retrieved from the TDx.TDxDevice.Sensor interface. It is that reference which has to be kept alive.Are you keeping a reference to the device object or why are you creating new instances of the Sensot object?
Kind regards,
Erik
Hi,
Just to be explicit. Here is my argument in C#:
Kind regards,
Erik
Just to be explicit. Here is my argument in C#:
Code: Select all
namespace TDxTest
{
public partial class Form1 : Form
{
TDx.TDxInput.Device device;
TDx.TDxInput.Sensor sensor;
long counter;
public Form1()
{
InitializeComponent();
device = new TDx.TDxInput.Device();
device.Connect();
sensor = device.Sensor;
sensor.SensorInput += new TDx.TDxInput._ISensorEvents_SensorInputEventHandler(sensor_SensorInput);
}
private void sensor_SensorInput()
{
System.Diagnostics.Trace.Write("Sensor Input[" + counter.ToString() + "]\n");
++counter;
if (counter > 10)
{
// The following code should by design NOT have an effect on the input stream.
// BUT IT DOES - On my system the output stream terminates here.
System.Diagnostics.Trace.Write("Releasing reference to sensor and calling garbage collector.\n");
sensor = null;
System.GC.Collect();
}
}
}
}
Erik
Hi ebaklund,
Initial testing shows that you are right: currently you need to keep a reference to the Sensor to keep on receiving events.
What seems to be happening is that the the garbage collection results in something equivalent to
i.e. The Sensor object still exists and can be accessed from the Device, however the event handler has been removed from the Sensor.
This also happens if you add the event handler using
Markus
Initial testing shows that you are right: currently you need to keep a reference to the Sensor to keep on receiving events.
What seems to be happening is that the the garbage collection results in something equivalent to
Code: Select all
sensor.SensorInput -= MyEventHandler;
This also happens if you add the event handler using
Code: Select all
device.Sensor.SensorInput += MyEventHandler;
-
- Posts: 18
- Joined: Wed May 28, 2008 11:35 am
Win. XP
SpacePilot
C#
I'm having a problem with the event listeners. We'll focus on what's necessary, my program listens for button presses, once a button is pressed it calls load preferences and changes the preferences on my SpacePilot(this is done solely to change the LCD screen). Whenever I call loadPreferences it works THE FIRST TIME ONLY. After the first time it calls loadPreferences my program will still receive button input from the device however any further calls to loadPreferences do not take effect. I'm thinking that my program still receives the data but thinks the device has changed or something and won't load a new preference.
Any help you can offer would be amazing. Thank you in advance,
~Nick~
SpacePilot
C#
I'm having a problem with the event listeners. We'll focus on what's necessary, my program listens for button presses, once a button is pressed it calls load preferences and changes the preferences on my SpacePilot(this is done solely to change the LCD screen). Whenever I call loadPreferences it works THE FIRST TIME ONLY. After the first time it calls loadPreferences my program will still receive button input from the device however any further calls to loadPreferences do not take effect. I'm thinking that my program still receives the data but thinks the device has changed or something and won't load a new preference.
Any help you can offer would be amazing. Thank you in advance,
~Nick~
"Know something about eveyrthing, and everything about something."
-
- Posts: 18
- Joined: Wed May 28, 2008 11:35 am
Yes, I did that correctly, and I know this is true, because I had it working when I was using DirectInput to poll the device rather than an event handler. Now that I have switched over to an event handler it doesn't work. Also, I'm sure that the config files work correctly and I'm referencing them right because I can get one to display each time I run the program. It's just that I can't get multiple preferences to load.
So I've tested a few theories. At the very beginning of the program I load a basic preference, then later as deemed by button presses I can still change the profile, so it can in fact load multiple in one run of the program.
My system is setup with a switch that jumps to a specific call to load preference depending on which button was pressed. I've tried putting a different loadPreference call at the end of the switch. When this runs, it loads the correct preference then loads the one I put at the end, thus showing it can in fact load multiple preferences in one method, during one run of the program...
I tried putting in multiple calls to loadPreference one right after the other to see if they can load simultaneously, and it works.
However, while the program is running if I press a button, and then after that specific preference loads I push another button a new preference is not loaded, however, I know from some textIO debugging that it is still getting into the correct location in the switch statement, and executes the line before, hits the new call to loadPreferences(but doesn't load it), then executes the line after.
I've also put in breakpoints and walked through the program and it indeed steps onto the every call to load preferences, but only the first one gets executed correctly.
Do I need to disconnect and then reconnect, or maybe even disconnect make a new reference to the device, connect, make new event handlers? I'm really digging for some sort of solution to this, but I can't seem to find it.
Again, thanks for your help,
~Nick~
So I've tested a few theories. At the very beginning of the program I load a basic preference, then later as deemed by button presses I can still change the profile, so it can in fact load multiple in one run of the program.
My system is setup with a switch that jumps to a specific call to load preference depending on which button was pressed. I've tried putting a different loadPreference call at the end of the switch. When this runs, it loads the correct preference then loads the one I put at the end, thus showing it can in fact load multiple preferences in one method, during one run of the program...
I tried putting in multiple calls to loadPreference one right after the other to see if they can load simultaneously, and it works.
However, while the program is running if I press a button, and then after that specific preference loads I push another button a new preference is not loaded, however, I know from some textIO debugging that it is still getting into the correct location in the switch statement, and executes the line before, hits the new call to loadPreferences(but doesn't load it), then executes the line after.
I've also put in breakpoints and walked through the program and it indeed steps onto the every call to load preferences, but only the first one gets executed correctly.
Do I need to disconnect and then reconnect, or maybe even disconnect make a new reference to the device, connect, make new event handlers? I'm really digging for some sort of solution to this, but I can't seem to find it.
Again, thanks for your help,
~Nick~
"Know something about eveyrthing, and everything about something."