Solved

WriteFile and CloseHandle seem to hang until further input

Posted on 2004-08-11
17
3,375 Views
Last Modified: 2008-01-09
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 ?
 
0
Comment
Question by:somnatic
  • 9
  • 4
  • 2
  • +2
17 Comments
 
LVL 5

Expert Comment

by:lemmeC
Comment Utility
The thread for reading seems to be having a higher priority. Try using the same priority for the ReadFile and WriteFile threads.
0
 
LVL 5

Expert Comment

by:lemmeC
Comment Utility
Or the WriteFile Thread could be waiting for some data set in the ReadFile Thread.
0
 
LVL 4

Author Comment

by:somnatic
Comment Utility
hmm .. how can i set the priority in C# ?
0
 
LVL 4

Author Comment

by:somnatic
Comment Utility
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
 
LVL 7

Expert Comment

by:aib_42
Comment Utility
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
 
LVL 4

Author Comment

by:somnatic
Comment Utility
@ 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
 
LVL 4

Author Comment

by:somnatic
Comment Utility
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
 
LVL 4

Author Comment

by:somnatic
Comment Utility
forget that last one ...

caps suck ;)
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 22

Expert Comment

by:grg99
Comment Utility
You're on the right track.  Use overlapped I/O, or pass your write data to a thread that does the actual write.
0
 
LVL 4

Author Comment

by:somnatic
Comment Utility
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
 
LVL 7

Expert Comment

by:aib_42
Comment Utility
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
 
LVL 7

Expert Comment

by:aib_42
Comment Utility
Typos, grammar mistakes, sleepiness, 9:25am. Please excuse the orc.
0
 
LVL 4

Author Comment

by:somnatic
Comment Utility
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
 
LVL 4

Author Comment

by:somnatic
Comment Utility
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
 
LVL 7

Assisted Solution

by:aib_42
aib_42 earned 250 total points
Comment Utility
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
 
LVL 19

Accepted Solution

by:
drichards earned 250 total points
Comment Utility
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
 
LVL 4

Author Comment

by:somnatic
Comment Utility
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

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now