|
Put the code in a <pre> block, not <code> - <pre> preserves spacing.
--Mike--
Friday's GoogleFight results: Britney Spears 2,190,000 - Erica Weichers 23
1ClickPicGrabber - Grab & organize pictures from your favorite web pages, with 1 click!
My really out-of-date homepage
Sonork-100.19012 Acid_Helm
|
|
|
|
|
First, don't call ResetEvent() after calling WaitCommEvent(). Your resetting the event which may have gotten set between your call to WaitCommEvent() and your call to ResetEvent(). You should do the ReadFile() first, then wait again, and get rid of the WaitForMultipleObjects. Additionally, I wouldn't use a separate event to signal the thread to quit. I'd just add another member variable for that, or even better, just set the thread handle to NULL. Lastly, you need to ensure your timeouts are set correctly. I've added a sample of what it should like at the end. Below is my implementation of your thread (some stuff removed for brevity, some errors not checked, and probably a few typo's, but you'll get the drift).
for (;;)
{
WaitCommEvent(....);
//check if WaitCommEvent succeeded or failed
if (GetLastError() != ERROR_IO_PENDING){
//something went horribly wrong with WaitCommEvent(), so
//clear all errors and try again
DWORD comerrors;
ClearCommError(pSerial->m_hIDComDev,&comerrors,0);
}else{
//IO is pending, wait for it to finish
if (GetOverlappedResult(pSerial->m_hIDComDev,&pSerial->OverlappedRead,&dwBytes,TRUE)){
//event occurred, see if it was an RX CHAR event
if (dwEvent == EV_RXCHAR){
pSerial->HandleIncomingData()
}else{
//event wasn't an RXCHAR... This can happen if someone changed
//the event mask (a common way to signal the thread to quit)
//so check if we were signaled to quit
if (pSerial->m_hRxThread == NULL)
break;
else
//else the event mask got all buggered up, so reset it
SetCommMask(pSerial->m_hIDComDev,EV_RXCHAR);
}//dwEvent == EV_RXCHAR
}else{
//GetOverLappedResult() result failed... handle that here
...
}
//now reset the event handle so we can start all over again
ResetEvent(pSerial->OverlappedRead.hEvent);
}
void CSerial::HandleIncomingData()
{
DWORD chars_read =0;
bool bDone = false;
//loop until there's no data in the rx buffer
while (!done){
ResetEvent(m_osRead.hEvent);
if (!ReadFile(m_hIDComDev,m_pIncomingData+m_dwDataIndex, m_cbDataBuf-
m_dwDataIndex, &chars_read,&OverlappedRead)){
if (GetLastError != ERROR_IO_PENDING){
//read failed, so just exit
done = true;
continue;
}else{
//read pending, wait for it to complete
DWORD dwRes = WaitForSingleObject(m_osRead.hEvent,INFINITE);
switch (dwRes){
case WAIT_OBJECT_0: //read event has completed
//did the read fail?
if (!GetOverlappedResult(m_hPort,&m_osRead,&chars_read,FALSE)){
done = true; //yep, break out
continue;
}else{
//read succeeded, did we read in any chars?
if (chars_read == 0){
//nope, so we timed out
done = true;
continue;
}else{
//read in some chars, so increment the index
m_dwIndex += chars_read;
//resize the data buffer if necessary
if (m_dwIndex >= m_cbDataBuf)
ResizeBuffer();
}
}
break;
default:
//got an error, so we are definitely done
done = true;
break;
}
}
}else{
//ReadFile succeed immediately, handle the chars
if (chars_read > 0)
m_dwIndex += chars_read;
else
done = true;
if (m_dwIndex >= m_cdDataBuf)
ResizeBuffer();
}
}
}
To signal the thread to quit, do the following:
void CSerial::StopRxThread()
{
//save a copy of our handle
HANDLE temp = m_hRxThread;
//signal the thread to quit by setting the handle to NULL
m_hRxThread = NULL;
//change the event mask to none. This will let the thread
//continue if it's waiting for WaitCommEvent() or
//GetOverlappedResult()
SetCommMask(m_hIDComDev,0);
//wait for the thread to exit
WaitForSingleObject(temp,THREAD_STOP_TIMEOUT);
//thread exited, close the handle
CloseHandle(temp);
}
Lastly, the code for setting the port timeouts
void CSerial::SetPortTimeouts()
{
COMMTIMEOUTS to={0};
to.ReadIntervalTimeout = MAXDWORD;
to.ReadTotalTimeoutMultiplier = MAXDWORD;
to.ReadTotalTimeoutConstant = (DWORD)m_lCommTimeout; // in milliseconds
to.WriteTotalTimeoutConstant = (DWORD)m_lCommTimeout; // in milliseconds
if (m_hPort != 0)
::SetCommTimeouts(m_hPort,&to);
}
Hope this helps,
Pat
|
|
|
|
|
Thanks!
Before I saw your reply, I thought there might be a race condition involving ResetEvent. For grins, I commented the ResetEvent code out, and it started working! I was worried because I didn't think WaitCommEvent should have cleared the manual event, and didn't understand why it was working. Your comments have put me at ease somewhat. Although I'm still not sure what mechanism is responsible for clearing the rxchar event before the call to WaitForMultipleObjects
Now I'll take a look at your suggested implementation. Thanks for the time you put into this!
GaryH
|
|
|
|
|
work_to_live wrote:
Although I'm still not sure what mechanism is responsible for clearing the rxchar event before the call to WaitForMultipleObjects
Ahh, I see where the confusion is. First, you never want the event cleared. You want the event in whatever state it is after WaitCommEvent() completes. If it's set, then you want WaitForMultipleObjects() to return immediately so you can beginning reading data, as that means data is available. If it's reset, then you want to wait until data becomes available, which will happen when the RXCHAR event occurs, and that will set the event.
For overlapped IO, WaitCommEvent() will always return immediately, and you need to check the return result to find out what happened. If the return result is TRUE, the function returned because the specified event occured, in which case the event handle will also be set. If the WaitCommEvent() returns FALSE, then you need to call GetLastError() to find out why. If the result is ERROR_IO_PENDING, only then can you wait on the event handle in the overlapped structure. If you look at my example, this will become plain.
What happened in your case where the thread appears hung was that WaitCommEvent() returned FALSE, and therefore the event handle is still reset. You then call ResetEvent(), but during the time, and RXCHAR event occurs and the event handle becomes set. You then reset it and wait on it, but since there is no mechanism to set the event now, the OS just waits forever.
There's also a problem for the case that WaitCommEvent() succeeds immediately. In that case, the event handle is set. You then immediately reset it and wait on it, which causes the same problem.
For your example, the only time it would work is if 1) WaitCommEvent() fails initially due to IO_PENDING, and then 2) the IO does not complete until after your call to ResetEvent().
There are only 2 times you should reset the event handle.
1) Before calling ReadFile()/WriteFile()
2) Before calling WaitCommEvent()
Never reset the event handle before a call to one of the WaitForxxx functions, or before a call to GetOverlappedResult(). If you do, the event can occur before the call to ResetEvent() completes, in which case the event will never become set again (like what happened here).
Hope this clears it up...
Pat
|
|
|
|
|
|
It's finally starting to sink in. I took one more pass through the WaitCommEvent documentation, and caught the one sentence I missed before... "When this happens, the system sets the hEvent member of the OVERLAPPED structure to the not-signaled state before WaitCommEvent returns" I missed that the previous 10 times I read it!
Thanks again.
|
|
|
|
|
|
I created a deskband and when I turn it on, it is checked. Is there a way to prevent it from becoming checked? I have put in the capability to have more than one band, but I can't create new ones because of this problem.
Thanks
|
|
|
|
|
in my program i have a linked list, which is circular and i need to print out the numbers in the list from a given number.
the number i have to print from is the third number (62) in the list (as shown below) to the end then it has to rap back around and print the first two numbers.any suggestions
92 82 62 72 99
it needs to print out
62 72 99 92 82
[code]
void ClosedList::PrintFrom(int item) const
{
NodeType* currPtr = head->backlink;
NodeType* newNodePtr = new NodeType;
newNodePtr->component = item;
newNodePtr->backlink = currPtr;
currPtr = newNodePtr;
newNodePtr = NULL;
if(!IsEmpty())
{
do
{
cout << currPtr->component << " ";
currPtr = currPtr->backlink;
}while (currPtr != head);
cout << currPtr->component << " ";
}
cout <<endl;
}
bool ClosedList::IsEmpty() const
{
return (head == NULL);
}
[/code]
|
|
|
|
|
If the list is circular, you need to remember the address of the starting point and check for that, so you know when you've looped around.
I'd write an iterator class, and then provide a method of using it to loop the list. I'd also make the print stuff an iostream inserter ( I have an article on this on the site ).
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
|
|
|
|
You need something like this:
struct List { List * next; void * data;};
// Walk to the nth node of the list.
List* walk_n(List * lst, unsigned n)
{
for(unsigned i=0; i<n; ++i) lst = lst->next;
return lst;
}
// Walk the list calling fn on each node (until
// the list loops back to the beginning)
void listWalk(List * lst, void(*fn)(void* data))
{
List * last = lst;
do
{
fn(lst->data);
lst = lst->next;
} while (last != lst);
}
With these two functions (which I made general since your
application serves best as a composition of general functions)
you can easily provide your required functionality.
void printFromN(List* lst, unsigned n)
{
listWalk(walk_n(lst, n), printFunction);
}
where print function is some function to output the data
in a list node.
Needless to say, this code is untested, as I just typed it,
but, although there might be a few typos, I hope it communicates
the basic idea.
Of course I have assumed no null lists, that is a whole other
subject that depends on exactly how you are defining your list
structure.
HTH
|
|
|
|
|
Hello,
I am creating a splitter window application where one of the windows is a CHTMLView view (in other words, a web browser). I was wondering if it is possible to put a control bar inside this splitter window, so that I can put labels and textboxes on it.
Does anyone know if this is possible? I was looking at Outlook Express, and it seems to have just that: in the splitter window where the email message is displayed, there is some sort of controlbar where the addressees and subject are displayed.
Does anyone know how to do this?
Thanks,
Trimtrom
|
|
|
|
|
some time mouse shows busy sign(or it is busy).
can any body tell how i may check that mouse is busy or not?
r00d0034@yahoo.com
|
|
|
|
|
errrrr if its eating cheese i guess its busy
otherwise it isnt
(ps: mice dont get busy the computer does)
"traffic lights are for people who can't make their own decisions" biz stuff about me
|
|
|
|
|
*grin* Yes, Imran does ask the same questions over and over again and gives the impression that he has no idea how to search for things himself. In this case, I had just finished explaining that you could poll the mouse position twice and see if it changes before I realised what he meant. Seeing as the busy cursor is just another cursor you set the mouse to, I am not sure there is a way to tell that this is the cursor being used, but I'm not sure.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
|
|
|
|
i could not understand wht you say .
plz explain it?
r00d0034@yahoo.com
|
|
|
|
|
I think she's pointing out that the mouse is never busy, it simply shows that the computer is. The rest of the comment was about real mice, living animals, and was obviously meant as a joke. ( Naturally, lauren is free to correct me here ).
I think it may be a little unfair to comment on your grasp of English, but I also think you bring it on yourself, because you seem to ask the same questions over and over, and the net impression is that you're feeding us your projects a bit at a time and not really looking to learn anything yourself. You should check msdn.microsoft.com as a bare minimum before postinmg a question, that site will answer pretty much every question you've asked about the WinNT login sequence, for example.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
|
|
|
|
any LogiTech webcam programmer here? QuickCam SDK?
norm
|
|
|
|
|
I dont know anything about the QuickCam SDK, but dont those devices have a TWAIN interface?
|
|
|
|
|
i downloaded the SDK and started playing with it. The samples are very simple and client implementation almost seems trivial - which is good.
I compiled the project and there's no compile time error and things looked good. The only problem is that it "cant connect to camera" (not using exact phrase here) for some reason. I have re-installed my webcam as well as the SDK and still have the same problem - well, i guess i will have to try do this on a different machine... more, the software that came with the webcam worked as normal. no error no nothing. but the sample project that came with the SDK didnt work for some reason (connection to camera)...
My question is: if u have experience with logitech webcam SDK, it'd be helpful if u can tell me such and such are the usual cause for problem associated with camera connection.
here's the URL:
http://developer.logitech.com/developer/
Thanks.
norm
|
|
|
|
|
one cool feature that comes with the logitech quickcam: motion detection =)
it would be cool if u can access the video/individual frames in realtime (image processing)... but perhaps that cant be done with avi.
i think u prolly need to do this by taking a sequence of still shots (jpeg or whatever format it supports) and process each frame individually... anyway, cool toy
norm
|
|
|
|
|
|
Hey guys
I have a CWinThread thread that I start off from a service. I also show a modeless dialog from this thread. My intention is to use SetThreadDesktop and to bring up the dialog box in one of the active virtual desktops. But my problem is that SetThreadDesktop fails and my dialog comes up in the current desktop. If I convert this to a worker thread (using CreateThread ) and then bring up my modeless dialog it works fine (I provide the message pump myself).
The document of SetThreadDesktop says this :-
The SetThreadDesktop function will fail if the calling thread has any windows or hooks on its current desktop (unless the hDesktop parameter is a handle to the current desktop).
My guess is that MFC threads do some hooking of their own and this is why SetThreadDesktop is failing. Does anyone know of any work-around to this issue?
Regards,
Nish
Author of the romantic comedy
Summer Love and Some more Cricket [New Win]
Review by Shog9
Click here for review[NW]
|
|
|
|
|
Don't know if this is going to help you, but in case you are playing with a service, make sure to check the "interactive user" in the service properties (this can be done programmatically as well).
|
|
|
|
|
.S.Rod. wrote:
Don't know if this is going to help you, but in case you are playing with a service, make sure to check the "interactive user" in the service properties (this can be done programmatically as well).
Yup, that option is already set
Nish
Author of the romantic comedy
Summer Love and Some more Cricket [New Win]
Review by Shog9
Click here for review[NW]
|
|
|
|
|