CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 3 FirstFirst 123 LastLast
Results 16 to 30 of 33
  1. #16
    Join Date
    Mar 2001
    Posts
    2,529

    Re: while loop w/ sleep(1) doesnt work

    I guess what I am saying is that Windows is not an RTOS #1 and #2 that not every version of Windows will provide what you need if you are using a thread. Windows XP will not be able to create a thread that reliably polls at the rate of 1ms. Windows Vista may be able to do this *more* reliably for you since it has been enchanced for multi-media purposes.

    Windows XP has a 10 ms quantum.

    Windiws Vista has 1 ms.

    As a side note, Windows 9X and Me have 55ms quantum.

    I have had speedier results with SetTimer than with threads.

    There are those who believe that sleep() with a parameter of > 0 is evil.
    eg: http://www.flounder.com/time.htm
    Last edited by ahoodin; January 6th, 2009 at 12:26 PM.
    ahoodin
    To keep the plot moving, that's why.

  2. #17
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by acerunner316 View Post
    i know about the canReadWait() function for kvaser. However, my app must also work with a few other CAN adapters that are user selectable. The APIs for these other devices do not have an equivalent function, so i have to write something in my app to do it.

    I have worked with a variety of CAN bus products over the past decade, and have never seen a commercial driver/library package that did NOT support notification. A few (typically raw, older ones) required an update in order for the adapter to generate a system interrupt..
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  3. #18
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: while loop w/ sleep(1) doesnt work

    Don't the other libraries have anything similar to this that you can use? http://www.kvaser.com/support/prodhe...m#using_handle
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  4. #19
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by VladimirF View Post
    Also, the “busy wait” is only wrong if you are counting crows in your loop. If you have something like that:
    Code:
    while(!canRead())
        ;
    not sure what you mean by "counting crow", but this is how this part of my program works

    In response to user clicking start button, I do this:
    while (!sequence complete)
    {
    //fill local buffer of CAN messages from hardware buffer using canRead()
    //search buffer for reply to cmd
    //if reply exist, send next cmd
    //if reply doesn't exist, continue loop to read more messages
    //sleep(1ms) to allow hardware buffer to fill
    }

    there's a lot more going on, but this is a very basic summary.

  5. #20
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by Codeplug View Post
    >> it's single thread.
    If you're not familiar with it, making it multi-threaded may add more complications than you care to deal with right now. But without it, you'll need to find a way to keep the UI responsive while handling CAN communications.

    The single threaded approach wouldn't be too hard if, for example, you had a modal dialog with a cancel button and some sort of progress indicator. You would then use a special message loop just for this modal dialog. This special message loop would periodically pump messages while handling CAN message/response pairs.

    gg
    no, i'm not familiar with multi-threading. I realize that's probably the better way to go in this situation...

    Can you elaborate on the modal dialog method? thanks

  6. #21
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by ahoodin View Post
    I have had speedier results with SetTimer than with threads.
    That's odd, I've tried using the SetTimer, and it is much much slower.
    Btw, I'm running on a XP system.

  7. #22
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by TheCPUWizard View Post
    I have worked with a variety of CAN bus products over the past decade, and have never seen a commercial driver/library package that did NOT support notification. A few (typically raw, older ones) required an update in order for the adapter to generate a system interrupt..
    I am using Kvaser, VectorCAN, and PeakCAN. If you know of such a function in those libraries, please advise. Thanks!

  8. #23
    Join Date
    Feb 2002
    Posts
    3,788

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by acerunner316 View Post
    I am writing a software that periodically checks for CAN messages through calls to the driver libraries. And I must perform actions depending on the CAN messages I see.

    At first I used a system timer and function call in response to the windows message WM_TIMER.
    (i.e. SetTimer(1,10,NULL) and OnTimer() function where the processing of the messages occur.)

    But that solution has proven to be too slow, and I need a faster loop. So I though to use a while loop with a sleep of 1ms so as not to lock up the cpu. However, I've read that the sleep interval can only be as low as 15ms, and anything below that will sleep for 15ms.

    How can I create a faster loop without using all cpu resources?

    long ago i had to do a similar thing and this is what i ended up doing:

    Code:
    HANDLE CMainFrame::m_hPortNotificationEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    
    // This sets up an event to notify the application if there
    			// are messages in the port‘s receive queue.
    			m_vErr = ncdSetNotification(m_vPortHandle,
    										(unsigned long *)&m_hPortNotificationEvent,
    										QUEUE_LEVEL);
    			if (m_vErr)
    				Error(m_vErr);
    
    // then i created a thread in suspended state
    
    // code inside the thread
    
    
    DWORD WINAPI CMainFrame::ReceiveData(LPVOID pVoid)
    {
    	DWORD dwResult = 0;
    	Vstatus vErr = 0;
    	Vevent *pEvent = NULL;
    	float fTimeStamp = 0;
    	char chTemp[100] = {0};
    	unsigned long ulMSGId = 0;
    	char chDataField[40] = {0};
    	CMainFrame *pThis = static_cast<CMainFrame *>(pVoid);
    	
    	while(TRUE)
    	{		
    		dwResult = WaitForSingleObject(m_hPortNotificationEvent, INFINITE);
    		switch(dwResult)
    		{
    			case WAIT_OBJECT_0:
    			
    				// receive
    				for (;;) // read all events
    				{
    					
    					vErr = ncdReceive1(m_vPortHandle,&pEvent);
    					if (vErr && vErr != VERR_QUEUE_IS_EMPTY)
    					{
    						if(pThis != NULL)
    						{
    							::MessageBox(pThis->m_hWnd, "A severe error has occured.\nHardware not present or badly installed.\nCheck (PCMCIA, Tranceiver cable, Connection to the MODAC) and try again.\nApplication will exit!",
    										IDS_S3,
    										MB_ICONERROR);
    							::SendMessage(pThis->m_hWnd, WM_CLOSE, 0, 0);
    						}
    					}
    					
    					if (vErr == VERR_QUEUE_IS_EMPTY)
    						break;
    					
    
    					if (pEvent->tag == V_RECEIVE_MSG) 
    					{.......
    if you're working with Vector's CANCard library all this should be familiar to you...
    Last edited by Alin; January 8th, 2009 at 03:49 PM.

  9. #24
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by acerunner316 View Post
    I am using Kvaser, VectorCAN, and PeakCAN. If you know of such a function in those libraries, please advise. Thanks!

    PeakCAN (which is ancient) does not. Typically this driver is best used on a thread wtih Huerestic delays.

    VectorCAN I cant find my documentation on, and most of the time I used it was with LabView (which has its own dedicated driver

    Kvaser we already determined does have it....

    Sounds like time for a decent class hierarchy and some background thread processing.
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  10. #25
    Join Date
    Nov 2003
    Posts
    1,902

    Re: while loop w/ sleep(1) doesnt work

    So I found documentation for all 3:
    I downloaded the "CAN Driver Library" from Vector here: https://www.vector-worldwide.com/vi_...center_en.html
    It has a "VCAND.pdf" documenting their API, including the functions that Alin showed us.

    I downloaded the "PCAN-PCI package" from Peak here: http://www.peak-system.com/Support.55.0.html?&L=1
    It has a "PCANLight_enu.chm" that documents its API. It is indeed a bare-bones API. The MFC sample that comes with it actually polls using SetTimer().

    And (again) the Kvaser API is documented online: http://www.kvaser.com/support/prodhelp/canlib38/

    So I wanted to get that out there and available to readers of this thread.


    Quote Originally Posted by acerunner316 View Post
    In response to user clicking start button, I do this:
    Code:
    while (!sequence complete)
    {
        //fill local buffer of CAN messages from hardware buffer using canRead()
        //search buffer for reply to cmd
        //if reply exist, send next cmd
        //if reply doesn't exist, continue loop to read more messages
        //sleep(1ms) to allow hardware buffer to fill
    }
    Getting back to your original issue - that you "need a faster loop" - Remove all calls to Sleep(). That's just wasting time. Instead, use canReadWait() with an arbitrary timeout (say 20ms) and let the loop run as fast as it wants to.

    Under Vector, you can achieve the same effect of canReadWait(20ms) by setting up a notification event and calling "WaitForSingleObject(m_hPortNotificationEvent, 20)" (using Alin's code).

    Under Peak, there is no "efficient waiting" for a message. My first attempt at this would be to create my own "canReadWait()" with something like this:
    Code:
    inline DWORD TimeElapsed(DWORD start, DWORD end)
    {
        if (end < start)
            return (0xFFFFFFFF - start) + end;
        return end - start;
    }//TimeElapsed
    
    DWORD Peak_canReadWait(TPCANMsg *MsgBuff, DWORD timeout)
    {
        DWORD res = CAN_Read(MsgBuff);
        if (res == CAN_ERR_QRCVEMPTY)
        {
            DWORD start = GetTickCount();
            SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
            for (;;)
            {
                res = CAN_Read(MsgBuff);
                if (res != CAN_ERR_QRCVEMPTY)
                    break;
                if (TimeElapsed(start, GetTickCount()) >= timeout)
                    break;
            }//for
            SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
        }//if
    
        return res;
    }//Peak_canReadWait
    Here we are still letting the loop run as fast as it wants (no sleeps). This will show a lot of CPU utilization, but at least you'll be "playing nicer" by lowering the priority while polling.

    >> Can you elaborate on the modal dialog method?
    It doesn't necessarily require a modal dialog. It's just a way to allow for user input and read from the device in a single thread. In other words, it would allow you to have a "Cancel" button to allow the user to break out of the "while (!sequence complete)" loop.

    gg

  11. #26
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    codeplug, thanks for the details explanations and the code sample.

    I've implemented the CanReadWait taht you describe above. Everything seems to work ok.
    However, I have a read-only editbox that displays status and percentage of the entire procedure, and this doesn't update anymore. It goes up to about 10&#37; and freezes. By looking at the CAN messages on a seperate software, I can see that the app is still running, only the interface seems to have frozen. If I click anything, the windows title displays the legendary "(not responding)" message until the entire process is done and I exist the while loop. Is there anyway to fix this?

    Thanks

  12. #27
    Join Date
    Feb 2002
    Posts
    3,788

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by acerunner316 View Post
    codeplug, thanks for the details explanations and the code sample.

    I've implemented the CanReadWait taht you describe above. Everything seems to work ok.
    However, I have a read-only editbox that displays status and percentage of the entire procedure, and this doesn't update anymore. It goes up to about 10% and freezes. By looking at the CAN messages on a seperate software, I can see that the app is still running, only the interface seems to have frozen. If I click anything, the windows title displays the legendary "(not responding)" message until the entire process is done and I exist the while loop. Is there anyway to fix this?

    Thanks
    did you at least take a look at my post? CAN messages are coming in way too fast for your interface to be responsive, so that's why you should be using a worker thread to do all the CAN processing and PostMessage to the UI when there is something you need to display.

  13. #28
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    alin, yes I did read your post. thanks for that btw.

    I am not familiar with multi-threading. I have only ever written simple dialog-based apps that perform a single task for each control item. Is multithreads the only way to go with what I'm trying to do here?

    thanks

  14. #29
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: while loop w/ sleep(1) doesnt work

    Multithreading is hardly ever the only way, but it's often the most convenient. And with the trend towards multi-core architectures, it's just a good skill to have in any case.

  15. #30
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    any recommendations on where I should start learning multi thread programming. Given that I am a self-taught programmer...well, windows programming. I learned intro C++ in school.

Page 2 of 3 FirstFirst 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured