CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Jul 2014
    Posts
    31

    How do you CWnd::SendMessage(...) a pointer to a string?

    The following throws an exception so what is the correct way of ding this?

    Code:
    void CBase::SendMessage(LPCSTR lpszMessage)
    {
    	static CString strMessage;
    
    	strMessage = lpszMessage;
    	m_pDlg->SendMessage(WM_UPLOAD_MESSAGE, (WPARAM)(LPCSTR)strMessage);
    }

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

    Re: How do you CWnd::SendMessage(...) a pointer to a string?

    What exception?
    And what is the receipient of this message?
    Victor Nijegorodov

  3. #3
    Join Date
    Jul 2014
    Posts
    31

    Re: How do you CWnd::SendMessage(...) a pointer to a string?

    Quote Originally Posted by VictorN View Post
    What exception?
    And what is the receipient of this message?
    Unhandled exception at 0x78c8217c (mfc100d.dll) in EasyWebStoreUploader.exe: 0xC0000005: Access violation reading location 0xfeeeff0e.

    The application is dialog based and the recipient of the message is the main dialog box.

  4. #4
    Join Date
    Jul 2014
    Posts
    31

    Re: How do you CWnd::SendMessage(...) a pointer to a string?

    As it turns out the exception has nothing to do with the string I am trying to send with SendMessage(...)

    This whole thread thing just seem impossible to acheive:

    When you click an 'upload all' button this function excutes:

    Code:
    void COtherFilesDialog::OnBnClickedButtonUploadWeb()
    {
    	CIniFile inifile(STR_INI_FILE_NAME);
    	CString strPublicHTML = inifile.getKeyValue("PublicHTML", "WebServer");
    	CFolder* pFolder = NULL;
    
    	if (((CEasyWebStoreUploaderDlg*)GetParent())->IsFtpConnected() && ValidateWebFolder(GetWebFolder()))
    	{
    		pFolder = CompileUploadList(GetWebFolder(), strPublicHTML);
    
    #ifdef _DEBUG
    		CStringArray strarrayUploadList;
    		pFolder->DebugOutput(false, strarrayUploadList);
    		((CEasyWebStoreUploaderDlg*)GetParent())->DebugOutput(strarrayUploadList);
    #endif
    		AfxBeginThread(UploadThread, pFolder);
    		delete pFolder;
    	}
    	else
    		((CEasyWebStoreUploaderDlg*)GetParent())->DoConnectionError();
    
    	((CEasyWebStoreUploaderDlg*)GetParent())->SetLastCtrlID(IDC_BUTTON_UPLOAD_WEB);
    }
    CompileUploadList(...) simply compiles a directory tree structure that lists all the files to upload to a web server and folders to create.

    Briefly the tree structure contains file elements (with just a path as in c:\folder\file.htm sort of thing) and folder elements (with a path as in c:\folder\file.htm and an array of mixed file and folder elements)


    Each element in the tree has a pointer to the main application dialog box window and a pointer to the active FTP connection. There are ASSERT_VALID test on all the copies of these and these pass as the tree structure is created.

    The actual uploading of all the files is done in a thread because it takes a little time to iterate through the tree structure and upload everything.

    So I am trying to use AfxBeginThread(UploadThread, pFolder);

    pFolder is a pointer to the first structure in the tree - the hard disk folder that contains all the stuff that I want to upload.


    Here is my thread function:

    Code:
    UINT __cdecl UploadThread(void *pParam)
    {
    	CFolder* pFolder = (CFolder*)pParam;	
    
    	ASSERT_VALID(pFolder);
    	pFolder->Upload();
    
    	return 0;
    }
    So the pointer that I passed to the thread passes the ASSERT_VALID test.

    Then I start the upload process - pFolder->Upload()

    Code:
    bool CFolder::Upload()
    {
    	bool bResult = false;
    	CFtpConnection* pFTP = m_pDlg->GetFtpConnection();
    	CString strFolder, strMessage;
    
    	ASSERT_VALID(pFTP);
    	if (pFTP)
    	{
    		strFolder = m_strServerFolder + m_strServerFolderSeperator + m_strNameOnly;
    		if (!pFTP->SetCurrentDirectory(strFolder))
    		{
    			ASSERT(pFTP->CreateDirectory(strFolder));
    			strMessage = "Creating folder '" + strFolder + "'...Success";
    			SendMessage(strMessage);
    			ASSERT(pFTP->SetCurrentDirectory(strFolder));			
    		}
    		for (int nI = 0; nI < m_array.GetCount(); nI++)
    			m_array[nI]->Upload();
    	}
    	return bResult;
    }
    All is good up until this line of code: if (!pFTP->SetCurrentDirectory(strFolder))

    The folder is successfully created on the web server as confirmed in Filezilla.

    But for some bizarre reason the function call also corrupts m_pDlg (pointer to the main dialog box window). Then when I try to send a message to it via m_pDlg->SendMessage(...) the unhandled exception is generated.

    I don't understand. Why would a successfully accessed pointer and a successfully executed function result in corruption of the containing object????

  5. #5
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: How do you CWnd::SendMessage(...) a pointer to a string?

    Quote Originally Posted by gregaryb View Post
    Code:
    		AfxBeginThread(UploadThread, pFolder);
    		delete pFolder;
    This part of your code looks wrong. You start the thread, but it does not mean thread will run right after that. Even if it will be running right after start does not mean it will finish before the main thread deletes (and propably) destroys the pFolder.
    So it could be the eason of your problem!
    You should delete pFolder only after the worker thread will exit!
    Victor Nijegorodov

  6. #6
    Join Date
    Jul 2014
    Posts
    31

    Re: How do you CWnd::SendMessage(...) a pointer to a string?

    Quote Originally Posted by VictorN View Post
    This part of your code looks wrong. You start the thread, but it does not mean thread will run right after that. Even if it will be running right after start does not mean it will finish before the main thread deletes (and propably) destroys the pFolder.
    So it could be the eason of your problem!
    You should delete pFolder only after the worker thread will exit!
    Thanks Victor. Did not even occur to me but it makes perfect sense.

    Apart form sending a completion windows message, is there any other way to determine when the thread has completed?

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

    Re: How do you CWnd::SendMessage(...) a pointer to a string?

    Messages is the best way, since other solutions would require polling (periodic testing) which makes your program ugly and inefficient.

    But... why don't you let the worker thread itself delete pFolder when it is no longer needed?
    Nobody cares how it works as long as it works

  8. #8
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: How do you CWnd::SendMessage(...) a pointer to a string?

    Quote Originally Posted by gregaryb View Post
    Thanks Victor. Did not even occur to me but it makes perfect sense.

    Apart form sending a completion windows message, is there any other way to determine when the thread has completed?
    Well, passing C++ objects across thread's boundaries is potentially unsafe, as the same object becomes accessible from multiple threads simultaneously.

    I would think about possibilities of creating local folder class instance based on some definitive but simplistic information really safe for passing between threads, like some UID, array index, or database id. Being created on thread it will be safe for deletion there on the thread.
    Best regards,
    Igor

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