Thread: Sleep question and a bug I can't figure out

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    89

    Sleep question and a bug I can't figure out

    First question: I want to make my program wait before continuing but when I use Sleep() it temporarily hangs my program and the GUI becomes completely unresponsive which is annoying and just doesnt seem right. I need to use Sleep in these places but is there anyway to do it differently so that my program just sits there for that amount of time without totally freezing up?

    Second question: I wrote a function to output some things to a telnet session. Tested it, works great. Now I wanted to call the function twice in a row and I started getting Assertion Failures. Since the function is dealing with a telnet server I thought maybe it was going to fast and screwing up so I put a Sleep(1000) in between the 2 calls and still have the problem. So then I go to debug and put a break point at the second function call, when it hit the break I immediatly hit Continue and it worked fine. So why in the world would this happen? If it pauses at the break point for 1 second it works but if I let it sleep for 1 second it doesnt. WTF??

  2. #2
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    sleep() sits there and does nothing till the specified time is up aka it blocks. use

    Code:
    UINT SetTimer(
    
        HWND hWnd,	// handle of window for timer messages
        UINT nIDEvent,	// timer identifier
        UINT uElapse,	// time-out value
        TIMERPROC lpTimerFunc 	// address of timer procedure
       );
    second think you are trying to reopen port already open .... need to look at code?

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    89
    Okay so if I wanted to wait for 5 seconds on a button click could I just put this:

    Code:
    private: System::Void bEdit_Click(System::Object^  sender, System::EventArgs^  e) {
    			SetTimer(0, 0, 5000, 0);
    		 }
    I was trying to look at examples and came up with that. I dont need to specify the window, the event, or the process I just want it to sit, stay and be good for 5 seconds.
    Last edited by ac251404; 08-04-2006 at 12:51 PM.

  4. #4
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    It's actually SetTimer, but since you are using VC++.NET, you might look into I think Timer controls?

    http://msdn2.microsoft.com/en-us/lib...ers.timer.aspx

    Your second problem is wierd, and code would probably help.

  5. #5
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    i am not sure about your c++ stuff but settimer() is what you want to use. You can handle the wm_timer message or set a timerproc to do you stuff in. you should have atleast a timer id so that you know which timer you are using. think defalt is 0. elaps time is in miliseconds so 5000 would be 5 sec but the timer is not acurate for 30 miliseconds or so. so within 30miliseconds you should get a message to handle.

    Code:
    /* timer.c by kryptkat */
    
    #include <windows.h>
    #include <stdio.h>
    
    VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent,DWORD dwTime)
    {
    	printf("timer expired meow \n");
    }
    
    int main(void)
    {
    	MSG Msg;
    
    	/* Set up the timer to go off every second */
    	SetTimer(NULL,0,1000,TimerProc);
    
    	/* Process all messages */
    	while(GetMessage(&Msg, NULL, 0, 0) > 0)
    	{
    		TranslateMessage(&Msg);
    		DispatchMessage(&Msg);
    	}
    	return 0;
    }
    this is the timerproc way. it will tick every second or if you do your 5sec it will tick every 5sec till you call killtimer() .

    Code:
    BOOL KillTimer(
    
        HWND hWnd,	// handle of window that installed timer
        UINT uIDEvent 	// timer identifier
       );
    see this is why you need a timer id. so you can kill the timer.

  6. #6
    Registered User
    Join Date
    May 2006
    Posts
    89
    yea that was a typo.

    As for the second problem I have traced the assertion failure to here:

    Code:
    String ^read;
    .....
    
    read = gcnew String(connector.ReadFromPipe().c_str());
    ......
    And here is ReadFromPipe():
    Code:
    string Pconnect::ReadFromPipe(){ 
       
       DWORD dwRead;
       string ret = "NULL";
       CHAR chBuf[BUFSIZE]; 
    
       // Close the write end of the pipe before reading from the 
       // read end of the pipe. 
       if (!CloseHandle(hChildStdoutWr)) 
         std::cerr << "Closing handle failed.\n";
     
       // Read output from the child process, and write to parent's STDOUT. 
       while(true){       
        DWORD dwAvail = 0;
        
    	//check if child process ended
    	if (!::PeekNamedPipe(hChildStdoutRd, NULL, 0, NULL, &dwAvail, NULL))  
          break;
    	//check if there was no data
        if (!dwAvail)           
           break;  
        //read the file and break once the reading is complete
        if(!ReadFile( hChildStdoutRd, chBuf, BUFSIZE, &dwRead, NULL) || dwRead == 0) 
    	   break;
       }
    
       //make sure there is data to put in the string
       if(dwRead > 0)
    		ret = chBuf;
    
       string::iterator it1;
       string::iterator it2;
    
      //parse out ANSI escapes
       for(it1 = ret.begin(); it1 != ret.end(); ++it1){
    	   if(*it1 == 0x1B){
    		   for(it2 = it1; it2 != ret.end()-1; ++it2){
    			   if(isalpha(*it2)){
    				   ret.replace(it1, it2+1, "");
    				   if(it1 != ret.begin())
    					   --it1;
    				   break;
    			   }
    		   }
    	   }
       }
      
       return ret;
    }
    The assertion failure says the following:
    Code:
    Debug Assertion Failed!
    
    Program: ...
    File: isctype.c
    Line: 56
    
    Expression: (unsigned)(c + 1) <= 256
    I understand what an assertion is but I cannot for the life of my think of why this would be causing one. Worst case scenario no data is read and it just returns the string NULL.

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    89
    I have to look more at this timer stuff but I really don't get it so far and I'm not sure why. I don't know if it is exactly what I need, I dont want to use it for recurring events or anywhere else or on anything I just want it to stop one time for 5 seconds (+-30ms doesnt matter). I was hoping there would be something like Sleep() that doesnt block. I am sure multi-threading and using sleep would work but I cant even figure out SetTimer let alone multi-threading lol. The timer stuff at that MSDN page just confused me even more but I'm gonna try and read it again more carefully. It may help more if I explain what I am doing also. The button launches a SSH session and logs into it but the server has a 5 second splash screen, so when they hit the Connect button I have text that says "Connecting" and when its done it says "Connected" but I don't want the user to think they are connected until past the splash screen. Sorry if that makes little sense, it is Friday and my brain is friend but I really want to get this working.
    Thanks

  8. #8
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Can you show us where the assertion error occurs? The STL replace function will invalidate iterators. You might look at this 'remove/erase' idiom FAQ:

    http://www.codeguru.com/forum/showth...ht=erase+idiom

    Or also at the string's replace and erase methods:

    http://www.halpernwightsoftware.com/...html#strings14
    http://www.halpernwightsoftware.com/...html#strings15

    Or also at STL remove and replace algortihms

    http://msdn.microsoft.com/library/de...TL_Sample).asp
    http://msdn.microsoft.com/library/de...TL_Sample).asp

    Will the user think that they're connected if it's...um...'connecting'?

  9. #9
    Registered User
    Join Date
    May 2006
    Posts
    89
    well I removed the ANSI parsing part of my code and it seems to have solved the assertion issue. Still looking for a viable pseudo-sleep method

  10. #10
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    You want to like, wait 5 seconds, and then do something, without hanging the GUI? I told you, man, timer controls: http://msdn2.microsoft.com/en-us/lib...ers.timer.aspx

  11. #11
    Registered User
    Join Date
    May 2006
    Posts
    89
    Okay, I am trying to implement a timer to test it out but I am getting a little hung up. Now the timer can call OnTimedEvent after the interval which is a static member function. I made OnTimedEvent a member of my Form class and I initialized the timer inside a Button Click. The problem is because the OnTimedEvent is static I cannot reference any of the elements of my form such as a textbox (dont really understand why). So I tried making a seperate non-static function and calling it from OnTimedEvent which obviously did not work. Here is the code I tried:

    Code:
    private: System::Void bConnect_Click(System::Object^  sender, System::EventArgs^  e) {
    
    				 System::Timers::Timer^ slpTimer = gcnew System::Timers::Timer;
    
    				 slpTimer->SynchronizingObject = this;
    
    				 slpTimer->Elapsed += gcnew ElapsedEventHandler( Form1::OnTimedEvent );
    
    				 // Set the Interval to 2 seconds (2000 milliseconds).
    				 slpTimer->Interval = 5000;
    			     slpTimer->Enabled = true;
    
    				 rOutput->Text = "Should see this after 5 sec.";
    				 rOutput->Refresh();
    				 
    GC::KeepAlive(slpTimer);
    
    }
    Well I'm sure you can see that it didnt work as I hoped. I think it is because the timer executes a new thread to wait on what it is doing and then the code keeps going. So that is when I tried using OnTimedEvent and got stuck:
    Code:
    private: void OnTimedEvent( Object^ /*source*/, ElapsedEventArgs^ /*e*/ )
       {
    	   		 rOutput->Text = "TEST";
    			 rOutput->Refresh();
       }
    Which gives the errors:
    Code:
    error C2227: left of '->Text' must point to class/struct/union/generic type
    error C2227: left of '->Refresh' must point to class/struct/union/generic type
    Now another thing I would like to eventually use this for is sending instructions to another piped program. I already have all that setup but I want to wait like 300ms between each send and each recieve between the 2 programs. I think I figured out a way to use this event timer to do it, tell me if this sounds like a decent plan - Generate queue of instruction strings I want executed. Call the event timer and somehow pass my queue by reference to the OnTimedEvent (how could I do this?). Then every 300ms (the interval) it will pop off an instruction, send it thru the pipe, wait 300ms and read info back and then go back to waiting. Lastly, if this does seem like a reasonable approach, how could I tell the timer to stop after the last instruction? In the OnTimedEvent can I just put like (psuedo-code):
    If queue is empty
    slpTimer->Enabled = false;

    Thanks

Popular pages Recent additions subscribe to a feed