I have what may be a fairly simple problem to anyone familiar with implementing anonymous methods.
The first code snippet below shows the typical code-is-working state. A global static IntPtr is declared in the code to serve as a handle for some interop code, and is give a value when dllComOpen() runs. The static variable commHandle is then used in any operation that reads/writes to the USB device. As we used to say in the Navy, "works fine, lasts a long long time, and drains to the bilge."
Although fairly infrequent, the call to dllComOpen() sometimes hangs waiting for the USB device when it's in a confused state. The result is that the UI doesn’t appear to the user because the backend code is hung up waiting on the dllComOpen() to finish. So I wrote a wrapper of sorts - an anonymous method to implement the otherwise working code; only in a separate thread. This way, I thought I could kick off dllComOpen() and sense if there’s a problem without hanging the main thread up. When executed, the code indeed opens the USB communications port and passes back a what appears to be a valid handle, except that any subsequent use of that handle seems to fail!
No errors are thrown, no complaints from the compiler, nothing. The handle looks good – appears valid (and very much the same as when I don’t use the anonymous method) – so I’m puzzled as to why I’m not seeing errors if the code needs some kind of “invoke” or has some sort of invalid access to the static commHandle variable… and here I thought static vars were great for inter-thread operations.
Anyway, must be too close to the trees today, because I’m just not seeing the forest. Any help appreciated.
// Global var
Private static IntPtr commHandle = (IntPtr)0;
...
//
// Code that works fine, but hangs waiting on the interop dllComOpen() if the USB device is confused
//
Public IntPtr OpenPort(int deviceID)
{
if (0 == (int)commHandle)
{
var res = dllComOpen(deviceID, out commHandle);
if ((int)res > 0)
{
dllComFlush(res);
this.IsOpen = ((int)res != 0);
}
}
}
//
// Code I tried – pretends to work, but any usage of the handle returns ‘command failed’
//
var res = (IntPtr)0;
Thread weAreAnonymous = new Thread(() =>
{
if (0 == (int)commHandle)
{
res = dllComOpen(deviceID, out commHandle);
if ((int)res > 0)
{
dllComFlush(res);
this.IsOpen = ((int)res != 0);
}
}
});
weAreAnonymous.Start();
// Now wait for a short time for thread to finish
Thread.Sleep(700);
if (weAreAnonymous.ThreadState == ThreadState.Running)
{
// Our Open() command has hung...so kill it
Notify("Failed to open interface.", IOSTATE.OPENFUBAR);
weAreAnonymous.Abort();
Thread.Sleep(250);
weAreAnonymous = null;
}
return commHandle;
...
The interesting thing is that when the USB port is ‘fine’ the check for ThreadState.Running is skipped because the port opens before the Thread.Sleep() is over. There is a valid, non-zero value in commHandle… you just can’t get the other interop functions to work when you pass the handle stored in it. Same code works WITHOUT the anonymous thread method wrapper (except for the part when the USB port is bolluxed.)
Genuine Rod Sirling? Stupid newbie mistake? Both? Neither?