11-13-2008 02:06 PM - edited 11-13-2008 02:07 PM
This problem is driving me crazy. It has to do with the GC trying to clean up after I have already disposed of a GpibSession, TcpipSession, or SerialSession object.
Here's my code for my Send function:
static string Send(String deviceAddr, String cmd)
{
GpibSession gpib = null;
string ret = "";
try
{
gpib = new GpibSession(deviceAddr, NationalInstruments.VisaNS.AccessModes.NoLock, 3000, false);
gpib.Write(cmd);
Thread.Sleep(55); // was 100;
}
catch ( Exception e )
{
return e.ToString();
}
if (gpib != null) gpib.Dispose();
return ret;
}
Very simple....now, after I make one call to this function: I get the following trace in NI SPY:
1. viOpenDefaultRM (0x00CE6338)
Process ID: 0x00000DD8 Thread ID: 0x00000100
Start Time: 14:36:04.059 Call Duration 00:00:00.031
Status: 0 (VI_SUCCESS)
2. viOpen (0x00CE6338, "GPIB::25::INSTR", 0, 3000, 0x00D16F60)
Process ID: 0x00000DD8 Thread ID: 0x00000100
Start Time: 14:36:04.090 Call Duration 00:00:00.047
Status: 0 (VI_SUCCESS)
3. viInstallHandler (GPIB::25::INSTR (0x00D16F60), IO_COMPLETION, 0x003420F2, NULL)
Process ID: 0x00000DD8 Thread ID: 0x00000100
Start Time: 14:36:04.137 Call Duration 00:00:00.000
Status: 0 (VI_SUCCESS)
4. viWrite (GPIB::25::INSTR (0x00D16F60), "AVER ON", 7, 7)
Process ID: 0x00000DD8 Thread ID: 0x00000100
Start Time: 14:36:04.137 Call Duration 00:00:00.000
Status: 0 (VI_SUCCESS)
5. viUninstallHandler (GPIB::25::INSTR (0x00D16F60), IO_COMPLETION, NULL, NULL)
Process ID: 0x00000DD8 Thread ID: 0x00000100
Start Time: 14:36:04.199 Call Duration 00:00:00.000
Status: 0 (VI_SUCCESS)
> 6. viUninstallHandler (GPIB::25::INSTR (0x00D16F60), IO_COMPLETION, NULL, NULL)
> Process ID: 0x00000DD8 Thread ID: 0x00000100
> Start Time: 14:36:04.199 Call Duration 00:00:00.000
> Status: 0xBFFF0028 (VI_ERROR_HNDLR_NINSTALLED)
7. viClose (GPIB::25::INSTR (0x00D16F60))
Process ID: 0x00000DD8 Thread ID: 0x00000100
Start Time: 14:36:04.199 Call Duration 00:00:00.000
Status: 0 (VI_SUCCESS)
8. viClose (0x00CE6338)
Process ID: 0x00000DD8 Thread ID: 0x00000100
Start Time: 14:36:04.199 Call Duration 00:00:00.000
Status: 0 (VI_SUCCESS)
I'm guessing the my Dispose() call fires off number "5",and then the GC tries to attempt 6 thru 8, but it's already disposed by me.
When I take out the Dispose() line, it works just fine w/o an error....however, this has VERY adverse effects on my program in the long run.
Any Suggestions?
11-14-2008 10:34 AM
nickm,
Dispose() releases all the references used by the GPIB session (in this case, gpib). It looks like your code is trying to release a reference right in a row and the second is causing the error. When you take out Dispose(), what does the NI-SPY capture look like? Do steps 5 and 6 both disappear or does just 6-8?
11-14-2008 10:38 AM - edited 11-14-2008 10:39 AM
Just like I said....it doesn't give the error: However, the viClose() are occuring because the .NET Garbage Collector is taking care of it when the function goes out of scope.
I want to implicitly call the Dispose(), and not have the GC do it.
THIS CODE HAS THE DISPOSE() LINE COMMENTED OUT:
1. viOpenDefaultRM (0x00CE6338)
Process ID: 0x000000D4 Thread ID: 0x00000E60
Start Time: 11:36:19.207 Call Duration 00:00:00.141
Status: 0 (VI_SUCCESS)
2. viOpen (0x00CE6338, "GPIB::25::INSTR", 0, 3000, 0x00D19880)
Process ID: 0x000000D4 Thread ID: 0x00000E60
Start Time: 11:36:19.348 Call Duration 00:00:00.047
Status: 0 (VI_SUCCESS)
3. viInstallHandler (GPIB::25::INSTR (0x00D19880), IO_COMPLETION, 0x003420F2, NULL)
Process ID: 0x000000D4 Thread ID: 0x00000E60
Start Time: 11:36:19.395 Call Duration 00:00:00.000
Status: 0 (VI_SUCCESS)
4. viWrite (GPIB::25::INSTR (0x00D19880), "AVER ON", 7, 7)
Process ID: 0x000000D4 Thread ID: 0x00000E60
Start Time: 11:36:19.395 Call Duration 00:00:00.000
Status: 0 (VI_SUCCESS)
5. viClose (GPIB::25::INSTR (0x00D19880))
Process ID: 0x000000D4 Thread ID: 0x00000A88
Start Time: 11:36:19.457 Call Duration 00:00:00.000
Status: 0 (VI_SUCCESS)
6. viClose (0x00CE6338)
Process ID: 0x000000D4 Thread ID: 0x00000A88
Start Time: 11:36:19.457 Call Duration 00:00:00.000
Status: 0 (VI_SUCCESS)
11-17-2008 04:14 PM - edited 11-17-2008 04:17 PM
nickm,
Have you used the GC.SuppressFinalize Method? ( http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx ) This would tell the system not to call the Finalize method for the object specified.
National Instruments
11-18-2008 06:19 AM
Caleb,
Thanks for your input...but there are some very adverse effects to supressing the GC. This 'send' function gets called so many times in my multi-threaded application, that invoking supress would cripple it.
There has got to be a better way. Why would NI write the Dispose() method only to have it produce an VISA error??
11-18-2008 09:01 AM
nickm,
Does that solve the problem for you? I understand that it may not be a final solution, but I want to verify where the problem is coming from.
National Instruments
11-18-2008 09:03 AM
No..it does not..when i use Suppress, it causes problems later on in my program.
11-18-2008 11:51 AM
Hello Nick,
It appears that this may be an issue with out internal implementation of the Session.Dispose() method. It appears that the Dispose method is calling viUninstallHandler twice. I have filed CAR #133767 to investigate this issue further. In the meantime, are you seeing any problems with your program as a result of viUninstallHandler being called twice? The error you are seeing only indicates that viUninstallHandler did not work the second time because the handler had already been uninstalled, but then things proceed without incident. As this is a fairly inconsequential error, if this error is the only thing that concerns you (meaning you are not seeing any runtime impact), I would advise you to continue calling Session.Dispose as you had been. Please don't hesitate to let me know if you have any further questions, or if you are indeed seeing run-time impact as a result of the error reported by Spy.
NickB
National Instruments
11-18-2008 12:04 PM - edited 11-18-2008 12:06 PM
Nick,
That was the answer I was looking for. I wanted to make sure that it wasn't something I was doing wrong.
Here's what's happening as a result of not properly closing sessions....
The function that i detailed above is a static function in one of my programs. For the sake of this discussion...let's just say that it HAS TO BE STATIC.
That means i could call this function thousands of times throughout the course of my program....which, subsequently creates and deletes many many MessageBasedSessions.
Randomly, after running for over 30 hours, the program will choke on a GPIB command and any MBS thereafter.
So, I ran NI Spy during this 30 hour session, and right around where we crashed, I found was that the GC kept trying to close a session that was already disposed of. Finally, a MSB that was created took on the same session/VI identification as the session that the GC was trying to close....and it just choked it.
So, naturally, my first reaction was to explicitly dispose of every session rather than just letting the GC handle it. This in turn lead to the errors from above, and it still chokes after long runs.
This could be a problem w/ the GC itself, or it could be a problem with your VISA .NET implementation. But I'd like to suggest, next time you release VISA, that you would unit test it by creating and disposing MSBs thousands of times, and making sure there are no errors in NI SPY.
Thank you very much for your help..and I will keep my eye out for the bug fix.
11-19-2008 08:36 AM
Hello Nick,
Just out of curiosity, what version of Visual Studio are you using to build your application?
Thanks!
NickB
National Instruments