• C

WriteFile and CloseHandle seem to hang until further input

So ... let's start :)

I have some USB device which reports as HID compliant Device. I can turn and push this device.

My program is written in C#, but it looks like the program lies with some of the API functions.

I can push and rotate this device and via ReadFile I can get the data (what has been done / rotated / pushed).

BUT:
I should also be able to write to that device (therefore 1 (maybe 2) bytes are sent to the device).
The Problem:
When I call WriteFile with the handle at first my whole program seems to hang (I watched it in the debugger and it looks like WriteFile doesn't do anything). When I now rotate (or push)  the device (so that some data should be sent from the device to my PC) the data reaches me and WriteFiles continues (and ends with success).

The same applies for CloseHandle

I call CloseHandle -> Everything hangs -> I move the device -> CloseHandle continues and succeeds (no error)


I do the reading in a separate Thread - so could this be the problem?

Can anyone out there maybe help me ?
 
LVL 4
somnaticAsked:
Who is Participating?
 
drichardsConnect With a Mentor Commented:
Overlapped IO is not really that hard once you've done it a few times.  Here's a basic read function you can run in a thread.  It's pieced together from some serial port code:
-------------------------------------
    OVERLAPPED olap;
    unsigned char buffer[1024];
    long result;
    DWORD wait = 1000;
    DWORD numRead, error;
    BOOL inProgress;
    HANDLE hPort;

    hPort = ::CreateFile("COM1", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    olap.Offset = 0;
    olap.OffsetHigh = 0;
    olap.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);

    inPorgress = FALSE;
    while ( 1 ) // Loop until exit condition is met
    {
        if ( !inProgress ) // check if a read is in progress already
        {
            result = -1;
            // No read in progress, so start one
            if ( ::ReadFile(hPort, buffer, 1024, &numRead, &olap) )
            {
                // Overlapped read returned immediately with data
                if ( numRead > 0 )
                {
                    result = buffer[0];
                }
            }
            else
            {
                // Check if operation pending or error
                error = GetLastError();
                if ( error == ERROR_IO_PENDING )
                {
                    inProgress = TRUE;
                }
                else
                {
                    // Handle error
                }
            }
        }

        if ( result == -1 ) // If no immediate result...
        {
            // Wait for 'wait' milliseconds (1 second in this example)
            if (WaitForSingleObject(olap.hEvent, wait) == WAIT_OBJECT_0)
            {
                // Didn't time out, so get the data and reset the event
                GetOverlappedResult(hPort, &olap, &numRead, FALSE);
                if ( numRead > 0 )
                {
                    result = buffer[0];
                }
                ResetEvent(olap.hEvent);
                inProgress = FALSE;
            }
        }

        if ( result != -1 )
        {
            // Process data here
        }

        // Check exit condition - I usually pass an event to the thread...
        // if ( WaitForSingleObject(hExitEvent, 0) == WAIT_OBJECT_0 ) break;
    }
------------------------------------------

0
 
lemmeCCommented:
The thread for reading seems to be having a higher priority. Try using the same priority for the ReadFile and WriteFile threads.
0
 
lemmeCCommented:
Or the WriteFile Thread could be waiting for some data set in the ReadFile Thread.
0
Become a Leader in Data Analytics

Gain the power to turn raw data into better business decisions and outcomes in your industry. Transform your career future by earning your MS in Data Analytics. WGU’s MSDA program curriculum features IT certifications from Oracle and SAS.  

 
somnaticAuthor Commented:
hmm .. how can i set the priority in C# ?
0
 
somnaticAuthor Commented:
ok . .found it out by myself ..

but that didn't help ...
I tried BelowNormal and Lowest, but nothing changed ..


Till now I think that:
* The thread which reads, has already called ReadFile(...)
* The thread which writes, calls WriteFile()
Now WriteFile has to wait until ReadFile has finished ...
then WriteFile is executed


any ideas ?
0
 
aib_42Commented:
If the reading thread is reading constantly, WriteFile might be blocking until the last ReadFile issued is completed, yes. I suggest you use the asynchronous I/O read function, ReadFileEx() to do your reading. While waiting for ReadFileEx's completion, the reading thread can check to see if the writer thread is issuing a WriteFile function call, and if it is, cancel its read attempt via CancelIO, to allow the write to go through.
0
 
somnaticAuthor Commented:
@ aib_42

that sounds like a possible solution .. do you have any code for this ?

i tried to cancel the ReadFile with CancelIo before, but nothing happened ...
0
 
somnaticAuthor Commented:
ok .. another one ...

I tried to build that OVERLAPPED structure in C# ...

Appearently I did at least something right:

            [StructLayout(LayoutKind.Sequential)]
                  private unsafe struct OVERLAPPED
            {
                  public int Internal;
                  public int InternalHigh;
                  public int Offset;
                  public int OffsetHigh;
                  public int Handle;
            }


but when I issue this structure (overlap = new OVERLAPPED) to
ReadFile(HidHandle, BufBytes, InputReportByteLength, ref BytesRead, ref overlap)

it says it can't convert from ....OVERLAPPED to int*

shouldn't ref give out the pointer ?
0
 
somnaticAuthor Commented:
forget that last one ...

caps suck ;)
0
 
grg99Commented:
You're on the right track.  Use overlapped I/O, or pass your write data to a thread that does the actual write.
0
 
somnaticAuthor Commented:
hmm .. what do you mean by the second part ?

why would I use another thread if I can't stop ReadFile to wait for input ?
0
 
aib_42Commented:
You may want to try switching to ReadFileEx() since "it is designed solely for asynchronous operation", quoting from the SDK reference :).

I have some synchronization ideas in mind, but I'm too sleepy to get my head together right now. If you still need advice by tomorrow (by when I will be at work ;) I can hopefully spit out some suggestions. Unfortunately, I have no source code at hand. (But I can give you a nice list of hacks and workarounds I had to try for a project, if you ever want to hate Win32 IPC.)

By the way, CancelIO has to be called from the thread which called the R/W operation (which also means that there is no way to block a synchronous operation). You would need the reading thread to check if there are any write requests and cancel its own read if so.
0
 
aib_42Commented:
Typos, grammar mistakes, sleepiness, 9:25am. Please excuse the orc.
0
 
somnaticAuthor Commented:
oh I excuse everything as long as it helps ;)

I tries ReadFileEx but couldn't get the thing with that Overlapped Structure right (too dumb probably).

concerning CancelIO ... did you have to say that ... ? that was exactely what I didn't want to hear ;)
0
 
somnaticAuthor Commented:
ahem .. and .. are u saying that there is no way at all to "cancel" that ReadFile operation ?

(i don't care if it's a beautiful way or not ;) )
0
 
aib_42Connect With a Mentor Commented:
Destroying the thread might help.. :)

I'm saying that there is not way to cancel a _synchronous_ ReadFile operation, since the thread doing the read will have to wait for ReadFile's completion before calling CancelIO, at which point there is not much point in calling it :).

Since you have to use overlapped structures anyway with an _asynchronous_ ReadFile operation, you might as well go ahead and use ReadFileEx, at least it can automatically call a function when it is done.

As for the OVERLAPPED structure (I am too dumb for it too), hmm, how about all fields zero? Doesn't look like you will be needing and of them.
0
 
somnaticAuthor Commented:
ooook .. now this looks like it could work ..

Thanks to all who answered in this Thread
I'll split the points to the two people who helped me most ...

Thank you all ...
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.