CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 24

Thread: Using one thread at a time with CSemaphore problem

  1. #1
    Join Date
    Sep 2014
    Location
    Las Vegas, NV
    Posts
    85

    Using one thread at a time with CSemaphore problem

    Hello
    I need some help using CSemaphore class in MFC C++ application. I have an edit1 box with multil ine and each line has a string. I'm trying to loop through edit1 box and for each string to start a thread that is using the string for specific function. I'm trying to limit the run of only one thread at the same time with semaphores but all treads start at the same time.
    So when i click button1 i loop through edit1 box and start threads:
    Code:
    void CMFCApplication1Dlg::onButton1Click()
    {
    	int i, nLineCount = edit1.GetLineCount();
    	
    	CString strText, strLine, mesaj;
    	for (i = 0; i < nLineCount; i++)
    	{
    		int len = edit1.LineLength(edit1.LineIndex(i));
    		edit1.GetLine(i, strText.GetBuffer(len), len);
    		strText.ReleaseBuffer(len);
    		strLine.Format(_T("%s"), strText);
    
    		THREADSTRUCT *_param = new THREADSTRUCT;
    		_param->dlsg = this;
    		_param->link = strLine;
    	CSemaphore semafor(1, 1); // here i limit only one instance of thread at a time ???
    		
    		CWinThread* tread[5];
    
    		tread[i] = AfxBeginThread(StartThread, _param);
    		 }
    }
    While looping through edit1 box multi line and starting the threads:
    Code:
    UINT CMFCApplication1Dlg::StartThread(LPVOID param)
    {
    	WaitForSingleObject(semafor, INFINITE); // wait for semafor to signal
    	THREADSTRUCT*    ts = (THREADSTRUCT*)param;
    // here i'm doing some operations with the string from edit1 box
    
    ReleaseSemaphore(semafor, 1, NULL); //release the semaphore for next thread to begin
    }
    Instead of running only one thread at a time all threads start. What am i doing wrong ?
    Thanks for your help!!!

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,734

    Re: Using one thread at a time with CSemaphore problem

    Quote Originally Posted by eclessiastes View Post
    While looping through edit1 box multi line and starting the threads:
    Code:
    UINT CMFCApplication1Dlg::StartThread(LPVOID param)
    {
    	WaitForSingleObject(semafor, INFINITE); // wait for semafor to signal
    	THREADSTRUCT*    ts = (THREADSTRUCT*)param;
    // here i'm doing some operations with the string from edit1 box
    
    ReleaseSemaphore(semafor, 1, NULL); //release the semaphore for next thread to begin
    }
    Instead of running only one thread at a time all threads start. What am i doing wrong ?
    And does this code compile???
    The thread function uses undeclared variable semafor!

    Besides, if you need one and only one thread at a time then just start the next one after the previous thread will have exited.
    Victor Nijegorodov

  3. #3
    Join Date
    Sep 2014
    Location
    Las Vegas, NV
    Posts
    85

    Re: Using one thread at a time with CSemaphore problem

    I'm trying to create a semaphore for multiple threads, i need to run only one thread at a time. I'm declaring the semaphore in my dialog file
    Code:
    HANDLE ghSemaphore = CreateSemaphore(NULL, 1, 1, NULL); // only one thread at once
    After i start the tread i call
    Code:
    WaitForSingleObject(ghSemaphore, 0L); // wait for this thread to execute before starting next thread
    Before the thread ends i call:
    Code:
    ReleaseSemaphore(ghSemaphore, 1, NULL); // previous thread finished work so release the next thread starts...
    It starts all treads instead of one tread once. Any idea please ? Thanks a lot!
    PS: where exactly should i declare createsemaphore , in button1command or in dialog .h file ?
    Last edited by eclessiastes; October 7th, 2014 at 01:42 AM.

  4. #4
    Join Date
    Jun 2002
    Location
    Stockholm, Sweden
    Posts
    1,641

    Re: Using one thread at a time with CSemaphore problem

    Code:
    WaitForSingleObject(ghSemaphore, 0L);
    This will not wait, it returns immediately. If your intention is to wait, use INFINITE as a parameter instead of 0.

    If your intention is to do something else in case another thread is executing, use a zero parameter and check the return value of WaitForSingleObject compared to WAIT_OBJECT_0.

    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
    Nobody cares how it works as long as it works

  5. #5
    Join Date
    Sep 2014
    Location
    Las Vegas, NV
    Posts
    85

    Re: Using one thread at a time with CSemaphore problem

    Thank you very much! It works now after much headache
    I declared in the main app:
    Code:
    HANDLE ghSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
    After the tread is started:
    Code:
    WaitForSingleObject(ghSemaphore, INFINITE);
    Before the tread ends:
    Code:
    ReleaseSemaphore(ghSemaphore, 1, NULL);

  6. #6
    Join Date
    Jun 2002
    Location
    Stockholm, Sweden
    Posts
    1,641

    Re: Using one thread at a time with CSemaphore problem

    I'm glad it helped.

    However, for the special case when you need to protect against concurrent access (i.e. exactly one thread is allowed), consider using a critical section instead of semaphore.
    Semaphore is slightly more heavyweight than a critical section, but it will only matter if your app uses the semaphore object very many times per second.

    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
    Nobody cares how it works as long as it works

  7. #7
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Using one thread at a time with CSemaphore problem

    If you need "one at a time", then the right synchronizing object is a mutex.
    A semaphor is intended for "2 to X" simultaneous accesses.

    what you are seeing is exactly what you are asking for
    you are creating a number of threads, and then waiting in the thread.

    it seems you have a totally wrong idea of how multithreading works. What you are basically doing right now doesn't even need threads at all. (ignoring the fact that the approach to what you seem to be doing is totally wrong).

  8. #8
    Join Date
    Sep 2014
    Location
    Las Vegas, NV
    Posts
    85

    Re: Using one thread at a time with CSemaphore problem

    So i'm creating 10 threads and each thread is inserting some items in a list control. i'm using semaphore because i don't want multiple threads to insert in list control at the same time because it will block the UI. Do you think i should critical section lock the list control after the thread starts and unlock it before the thread ends ? is this better idea than using semaphores ?

  9. #9
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,734

    Re: Using one thread at a time with CSemaphore problem

    Quote Originally Posted by eclessiastes View Post
    ... i don't want multiple threads to insert in list control at the same time because it will block the UI. Do you think i should critical section lock the list control after the thread starts and unlock it before the thread ends ? is this better idea than using semaphores ?
    Your approach is wrong! And you were already told about it as well as about the right way to implement it your your previous thread.
    Victor Nijegorodov

  10. #10
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,149

    Re: Using one thread at a time with CSemaphore problem

    i don't want multiple threads to insert in list control at the same time because it will block the UI.
    The only thread that should be updating the list control is the main UI thread. Other threads that want to update the control POST a message to the UI thread. The main UI thread processes these received messages and updates the control.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2019 (16.6.3)

  11. #11
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Using one thread at a time with CSemaphore problem

    you create 10 threads
    then have each thread waiting on a semaphore
    so only 1 thread can do soemthing useful at a time

    why are you making 10 threads, when you obviously only have 1 thread ever doing anything useful at any one point in time.

    the point of making multiple threads is to make them do some work AT THE SAME TIME.
    if for some reason this cannot happen because of synchronisation issues, then the fault is in creating more threads than you really need to have.

  12. #12
    Join Date
    Sep 2014
    Location
    Las Vegas, NV
    Posts
    85

    Re: Using one thread at a time with CSemaphore problem

    Quote Originally Posted by 2kaud View Post
    The only thread that should be updating the list control is the main UI thread. Other threads that want to update the control POST a message to the UI thread. The main UI thread processes these received messages and updates the control.
    Can you please give me a small example how to post message and how to received from main UI thread ?

  13. #13
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,734

    Re: Using one thread at a time with CSemaphore problem

    Quote Originally Posted by eclessiastes View Post
    Can you please give me a small example how to post message and how to received from main UI thread ?
    I already gave you a link in the post#2 (and then I mentioned it again in the post#14) in your another thread.
    Victor Nijegorodov

  14. #14
    Join Date
    Sep 2014
    Location
    Las Vegas, NV
    Posts
    85

    Re: Using one thread at a time with CSemaphore problem

    I defined :
    Code:
    #define UWM_ADDSTRING (WM_APP + 7)
    In message map i add:
    Code:
    ON_MESSAGE(UWM_ADDSTRING, OnAddString)
    In .h file i add
    Code:
    afx_msg LRESULT OnAddString(WPARAM, LPARAM);
    then
    Code:
    LRESULT CMFCApplication1Dlg::OnAddString(WPARAM, LPARAM lParam)
    {
    	CString * s = (CString *)lParam;
    	listct1.InsertItem(0,(*s));
    	delete s;
    	return 0;
    }
    And this is how i post message from thread
    Code:
    CString * s = new CString("listitem");
    	AfxGetMainWnd()->PostMessageW(UWM_ADDSTRING, 0, (LPARAM)s);
    Everything works ok so far. Is this the correct way to do it (postmessage) ?
    Last edited by eclessiastes; October 8th, 2014 at 01:57 PM.

  15. #15
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,302

    Re: Using one thread at a time with CSemaphore problem

    Quote Originally Posted by eclessiastes View Post
    I defined :
    Code:
    #define UWM_ADDSTRING (WM_APP + 7)
    In .h file i add
    Code:
    afx_msg LRESULT OnAddString(WPARAM, LPARAM);
    then
    Code:
    LRESULT CMFCApplication1Dlg::OnAddString(WPARAM, LPARAM lParam)
    {
    	CString * s = (CString *)lParam;
    	listct1.InsertItem(0,(*s));
    	delete s;
    	return 0;
    }
    And this is how i post message from thread
    Code:
    CString * s = new CString("listitem");
    	AfxGetMainWnd()->PostMessageW(UWM_ADDSTRING, 0, (LPARAM)s);
    Everything works ok so far. Is this the correct way to do it (postmessage) ?
    It's one way to do it. When you handle the message, be sure to clean up and delete the string (allocated with new).

Page 1 of 2 12 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
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)