Thread: API Thread HEADACHE

  1. #1
    Registered User
    Join Date
    May 2004
    Posts
    164

    Unhappy API Thread HEADACHE

    I have been trying to implement a single thread operation internal to a dialog window in my windows app. I have been all over the net, including this site and found alot of great examples, but nothing seems to be working. I have successfully followed the tutorials from the windows links on this site for Win32 console examples and built the nifty program for threads using _beginthread(), but all attempts to apply API based code has failed

    OS: windows XP
    Compiler: MS Visual C++ 6.0 Standard

    I created a new class derived from CWinThread successfully called Thread:
    Code:
    #if !defined(AFX_THREAD_H__9BC5C079_E9F6_42A7_B471_1CA97CC15BB6__INCLUDED_)
    #define AFX_THREAD_H__9BC5C079_E9F6_42A7_B471_1CA97CC15BB6__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // Thread.h : header file
    //
    
    
    class VIEWER;   //forward declaration to VIEWER dialog
    /////////////////////////////////////////////////////////////////////////////
    // Thread thread
    
    class Thread : public CWinThread
    {
    	DECLARE_DYNCREATE(Thread)
    protected:
    	Thread();           // protected constructor used by dynamic creation
    
    // Attributes
    public:
    
    // Operations
    public:
    
    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(Thread)
    	public:
    	virtual BOOL InitInstance();
    	virtual int ExitInstance();
    	virtual int Run();
    	//}}AFX_VIRTUAL
    	
    	void setOwner(VIEWER* ptrDialog)
    	{
    		ptrDlg = ptrDialog;  
    	}
    
    	private:
    		VIEWER* ptrDlg;	//the pointer to pointer to object dialog window: VIEWER
    
    // Implementation
    protected:
    	virtual ~Thread();	//protected destructor
    
    	// Generated message map functions
    	//{{AFX_MSG(Thread)
    		// NOTE - the ClassWizard will add and remove member functions here.
    	//}}AFX_MSG
    
    	DECLARE_MESSAGE_MAP()
    };
    
    /////////////////////////////////////////////////////////////////////////////
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    
    #endif // !defined(AFX_THREAD_H__9BC5C079_E9F6_42A7_B471_1CA97CC15BB6__INCLUDED_)
    I edited the Thread.cpp file to include my pointers to the dialog window I want to start and monitor the thread responses:
    Code:
    // Thread.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "FXG.h"
    #include "Thread.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /////////////////////////////////////////////////////////////////////////////
    // Thread
    
    IMPLEMENT_DYNCREATE(Thread, CWinThread)
    
    Thread::Thread()
    :ptrDlg(NULL)
    {
    }
    
    Thread::~Thread()
    {
    	ptrDlg = NULL;
    }
    
    BOOL Thread::InitInstance()
    {
    	// TODO:  perform and per-thread initialization here
    	return TRUE;
    }
    
    int Thread::ExitInstance()
    {
    	// TODO:  perform any per-thread cleanup here
    	return CWinThread::ExitInstance();
    }
    
    BEGIN_MESSAGE_MAP(Thread, CWinThread)
    	//{{AFX_MSG_MAP(Thread)
    		// NOTE - the ClassWizard will add and remove mapping macros here.
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // Thread message handlers
    
    int Thread::Run() 
    {
    	// TODO: Add your specialized code here and/or call the base class
    	
    	return CWinThread::Run();
    }
    Then I create a handle object in the dialog window, VIEWER, I want to initate the thread in:
    Code:
    HANDLE hThread;
    Then I go into my InitDialog function to add my call to _beginthreadex() since I want to start the thread as soon as the dialog is called:
    Code:
    //assign handle object to equal call to begin thread and pass
    //in argurments for Thread::Run()
    hThread=(HANDLE)_beginthreadex(NULL,0,Thread::Run,this,0,0);
    And I get the following errors returned:
    [cde]
    C:\ASE\FXG\VIEWER.cpp(79) : error C2664: '_beginthreadex' : cannot convert parameter 3 from 'int (__thiscall Thread::*)(void)' to 'unsigned int (__stdcall *)(void *)'
    There is no context in which this conversion is possible
    [/code]

    Please help, I have tried 15 different example programs, and been reading for days and not been able to solve the issue. BUT to be positive, I have learned alot that from my research, but I could use some assistance to get this resolved. Thanks again-

  2. #2
    Registered User
    Join Date
    May 2004
    Posts
    164
    Ok, in reading the error over and then reviewing MSDN notes I notice that it seems like I am passing the wrong type of call, which is why I am getting the type int conversion error to the _beginthreadex() call which apparently expects an address, which I assume is the class where the function is defined, class: Thread, and then the void function with declared pointer

    MSDN NOTE:
    Code:
    uintptr_t _beginthreadex( 
       void *security,
       unsigned stack_size,
       unsigned ( *start_address )( void * ),
       void *arglist,
       unsigned initflag,
       unsigned *thrdaddr 
    );
    can someone please show an example of how I should define the call to my class and the type of function with pointer? Or am I mistaken about what the error is saying?????

  3. #3
    Registered User
    Join Date
    May 2004
    Posts
    164
    question relating to MFC vs API

    Is the function _beginthreadex() API (NOT_MFC)?

    and

    AfxBeginThread() is the MFC version of _beginthreadex()?

  4. #4
    Registered User
    Join Date
    May 2004
    Posts
    164
    Although I don't think I got as much from the learning aspect, which i hope to change in the near future, I did find a good example program for the AfxBeginThread() on code project and it is working for me quite well once I was able to add it to my code. I have alot still to modify, but in case it helps anyone else and to say thanks to Enis, here is the project I downloaded and I am learning from:

    http://www.codeproject.com/threads/memberthread.asp

    But I would still appreciate any feedback available, I had hoped to go a less MFC route but I will take what I can get to work in order to push forward and hopefully learn what I need to learn.

  5. #5
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Windows API has a CreateThread function
    _beginthread/_beginthreadex are CRT wrappers for these functions, providing additional initializations required for other CRT functions to work properly in the multythreading environment

    MFC has CWinThread::CreateThread function and AfxBeginThread for the same reason
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  6. #6
    pwns nooblars
    Join Date
    Oct 2005
    Location
    Portland, Or
    Posts
    1,094
    Btw, it is Win32 API, not just API. I had no idea what API(application programming interface) you were talking about when I read the title of your post and had to actually read more to figure it out.

  7. #7
    Registered User
    Join Date
    May 2004
    Posts
    164
    Vart,
    thanks for helpful reply, I appreciate your assistance as always that helps.

  8. #8
    Registered User
    Join Date
    May 2004
    Posts
    164

    return value from inside thread

    I am tacking this onto my previous thread as it relates to the same problem and code, but the subject is slightly different....

    In using MFC's AfxBeginThread, the call to the threads are working, I put message box's inside the functions', the pointer to the threads call and got positive results so I know the thread is working, but now I am trying to figure out how to return the result of the polling thread to my Dialog Window. Not sure if this is something I need to define inside the definition of the function I call with the thread, or if there is some way to pipe the repsonse of the thread back to Dialog and an assigned variable.

    Class Declaration and the functions I call in the thread (ConfigurePort and ReadString):
    Code:
    class VIEWER : public CDialog
    {
    // Construction
    public:
    	void ControlCap();
    	VIEWER(CWnd* pParent = NULL);   // standard constructor
    	HANDLE hPort;
    
    	void setOwner(VIEWER* ptrDialog)
    	{
    		ptrDlg = ptrDialog;
    	}
    
    	static UINT StartThread (LPVOID param);
    	typedef struct THREADSTRUCT				//structure for passing to the controlling function
    	{
    		VIEWER*	_this;
    
    	} THREADSTRUCT;//controlling function header
    
    	//define functions for port settings and reading port
    	//the read byte function
    	BOOL ReadByte(BYTE  &resp)
    	{
    		BOOL bReturn = TRUE;
    		BYTE rx;
    		DWORD dwBytesTransferred=0;
    
    		if (ReadFile (hPort, &rx, 1, &dwBytesTransferred, 0)> 0)
    		{
    			if (dwBytesTransferred == 1)
    			{
    				resp=rx;
    				bReturn  = TRUE;
    			}
    			else bReturn = FALSE;
    		}
    		else    bReturn = FALSE;
    		return bReturn;
    	}
    	//the read string function
    	BOOL ReadString(void *outstring, int *length)
    	{
    	//	MessageBox("In ReadString");
    		BYTE data;
    		BYTE dataout[4096]={0};
    		int index = 0;
    		while(ReadByte(data)== TRUE)
    		{
    			dataout[index++] = data;
    		}
    		memcpy(outstring, dataout, index);
    		*length = index;
    		return TRUE;
    	}
    	//the serial port configuration function
    	HANDLE ConfigureSerialPort(LPCSTR lpszPortName)
    	{
    //		MessageBox("In ConfigPort");
    		HANDLE hComm = NULL;
    		DWORD dwError;
    		DCB PortDCB;
    		COMMTIMEOUTS CommTimeouts;
    		// Open the serial port.
    		hComm = CreateFile (lpszPortName, // Pointer to the name of the port
    			GENERIC_READ | GENERIC_WRITE,
    			// Access (read-write) mode
    			0,              // Share mode
    			NULL,           // Pointer to the security attribute
    			OPEN_EXISTING,  // How to open the serial port
    			0,              // Port attributes
    			NULL);          // Handle to port with attribute to copy
    		// Initialize the DCBlength member.
    		PortDCB.DCBlength = sizeof (DCB);
    		// Get the default port setting information.
    		GetCommState (hComm, &PortDCB);
    		// Change the DCB structure settings.
    		PortDCB.BaudRate = 9600;              // Current baud
    		PortDCB.fBinary = TRUE;               // Binary mode; no EOF check
    		PortDCB.fParity = TRUE;               // Enable parity checking
    		PortDCB.fOutxCtsFlow = FALSE;         // No CTS output flow control
    		PortDCB.fOutxDsrFlow = FALSE;         // No DSR output flow control
    		PortDCB.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type
    		PortDCB.fDsrSensitivity = FALSE;      // DSR sensitivity
    		PortDCB.fTXContinueOnXoff = TRUE;     // XOFF continues Tx
    		PortDCB.fOutX = FALSE;                // No XON/XOFF out flow control
    		PortDCB.fInX = FALSE;                 // No XON/XOFF in flow control
    		PortDCB.fErrorChar = FALSE;           // Disable error replacement
    		PortDCB.fNull = FALSE;                // Disable null stripping
    		PortDCB.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control
    		PortDCB.fAbortOnError = TRUE;        // Do not abort reads/writes on error
    		PortDCB.ByteSize = 8;                 // Number of bits/byte, 4-8
    		PortDCB.Parity = NOPARITY;            // 0-4=no,odd,even,mark,space
    		PortDCB.StopBits = ONESTOPBIT;        // 0,1,2 = 1, 1.5, 2
    
    		// Configure the port according to the specifications of the DCB structure.
    		if (!SetCommState (hComm, &PortDCB))
    		{
    			AfxMessageBox("Could not configure serial port\n");
    			return NULL;
    		}
    		// Retrieve the time-out parameters for all read and write operations
    		// on the port.
    		GetCommTimeouts (hComm, &CommTimeouts);
    		// Change the COMMTIMEOUTS structure settings.
    		CommTimeouts.ReadIntervalTimeout = MAXDWORD;
    		CommTimeouts.ReadTotalTimeoutMultiplier = 0;
    		CommTimeouts.ReadTotalTimeoutConstant = 0;
    		CommTimeouts.WriteTotalTimeoutMultiplier = 0;
    		CommTimeouts.WriteTotalTimeoutConstant = 0;
    		if (!SetCommTimeouts (hComm, &CommTimeouts))
    		{
    			AfxMessageBox("Could not set timeouts\n");
    			return NULL;
    		} 
    		return hComm;
    
    	} 
    
    
    	//the close port function
    	void ClosePort()
    	{
    		CloseHandle(hPort);
    		return;
    	}	
    
    // Dialog Data
    	//{{AFX_DATA(VIEWER)
    	enum { IDD = IDD_VIEWER };
    	CVideoCap	m_VideoCap1;
    	CString	m_City;
    	CString	m_State;
    	CString	m_Street;
    	CString	m_Speed;
    	CString	m_Radar;
    	//}}AFX_DATA
    
    private:
    	void UpdateConfig();
    	VIEWER* ptrDlg;
    
    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(VIEWER)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	//}}AFX_VIRTUAL
    
    // Implementation
    protected:
    
    	// Generated message map functions
    	//{{AFX_MSG(VIEWER)
    	virtual BOOL OnInitDialog();
    	afx_msg void OnChangeStreet();
    	afx_msg void OnChangeCity();
    	afx_msg void OnChangeSpeed();
    	afx_msg void OnSelchangeState();
    	virtual void OnOK();
    	afx_msg void OnCapture();
    	afx_msg void OnStop();
    	afx_msg void OnPause();
    	afx_msg void OnResume();
    	afx_msg void OnSnapshot();
    	afx_msg void OnChangeRadar();
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    
    #endif // !defined(AFX_VIEWER_H__4FE30814_FC1C_42DD_B76F_F060E2892084__INCLUDED_)

    and now the actual thread execution:
    Code:
    UINT VIEWER::StartThread (LPVOID param)
    {
    	ofstream fout;
    	fout.open("C:\\threadtest.txt", ios::app);
    	char data [10];
    	char clear [2] = "";
    	char message[8];
    	int sizeBuffer =8;
    	int count = 0;
    	THREADSTRUCT*	ts = (THREADSTRUCT*)param;
    	//open port and configure it
    	//here is the time-consuming process which interacts with your dialog
    //	AfxMessageBox ("Thread is started!");
     
    /*	ts->_this->m_ctrl_progress.SetRange (0, 1000);
    	while (ts->_this->m_ctrl_progress.GetPos () < 1000)
    	{
    		Sleep(500);
    		ts->_this->m_ctrl_progress.StepIt ();
    	} */
    	ts->_this->ConfigureSerialPort("COM1");
    	Sleep(500);
    	do
    	{
    	ts->_this->ReadString(message, &sizeBuffer);
    	count++;
    	Sleep(50);
    	if (count ==100)
    	{
    		ts->_this->ClosePort();
    		fout<<"eo data loop"<<endl;
    		fout.close();
    		break;
    	}
    	}while (count <=100);
    	//testing only
    	AfxMessageBox("Loop Completed");
    //	ts->_this->ClosePort();
    	
    	//you can also call AfxEndThread() here
    	AfxEndThread(0,NULL);
    	return 1;
    }
    I have tried creating some variables and setting them equal to the thread call, and this did not work:
    Code:
    static CString output;
    outp+=ts->_this->ReadString(message, &sizeBuffer);
    I get the message using the same code in a Win32 Console app (<- just for you Wraithan :-)) and I can "cout" the message string fine, so I know the exact string I should be seeing, but when trying to return in from a thread vs from the call to the function itself, nada.

    I will keep cracking at it, but any help would be appreciated -

  9. #9
    Registered User
    Join Date
    May 2004
    Posts
    164
    oh and yes the output vs outp was a typo, no errors when compiling. Ha Ha! Tried a few other variances, and got, what looks like garble to the output file, but still no difference, I think I am not truly getting the value of the variable, "message" into a point where I can output it to the dialog or to another variable.

    Which is odd to me, because, message is declared inside the dialog VIEWER::StartThread, so I would think what I am doing is ok:
    Code:
    char message[8];
    int sizeBuffer =8;
    ts->_this->ReadString(message, &sizeBuffer);
    //output to file
    fout<<message<<endl;
    calling the handle = to the reference of the function ReadString, and then output the variable message to the dialog or set it = to another global variable. But this is not working so I must be completely missing the point.....

  10. #10
    Registered User
    Join Date
    May 2004
    Posts
    164
    ok, brain fart....

    when I spawn the thread and call the ReadString function passing it the two variables, message and sizeBuffer...

    Are those variables not accessible because they are being used by the thread, a separate process from the originating dialog process????

    If so, would that mean I need a ptr declared inside the original class that would and assign that inside the function definition of ReadString so that it could return or provide a "pointer" to that value to return it to the dialog or a global variable of the dialog???

    Yes sorry, I talk to myself, it helps.....

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Threading is complicated. If you don't quite understand all the rules attached to it, I suggest you do some console programs to properly learn them, i.e. strike Win32 API and MFC from the equation.

    Threading in Win32 is more complicated. Threads may have attached message queues. Windows have a bit of thread affinity.

    Threading in MFC is hell. The wrapper objects cannot be transferred between threads. There's lots and lots of pitfalls associated with threading.


    If you're serious about using MFC and threads, I really recommend you search for the topic on the web, or get "Programming Windows with MFC" by Jeff Prosise.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #12
    Registered User
    Join Date
    May 2004
    Posts
    164

    Question

    I agree need some additional resources, not easy to find in local stores, But I did just order the book, Windows Programing With MFC online, so I should get it hopefully by the end of the week. Always good to have a reference:-)

    Still hoping to get some help if possible in the mean time....

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. multithreading in c
    By thebrighter in forum C Programming
    Replies: 8
    Last Post: 07-10-2007, 01:17 PM
  2. Replies: 2
    Last Post: 07-01-2007, 07:11 AM
  3. multithreading question
    By ichijoji in forum C++ Programming
    Replies: 7
    Last Post: 04-12-2005, 10:59 PM
  4. Win32 Thread Object Model Revisted
    By Codeplug in forum Windows Programming
    Replies: 5
    Last Post: 12-15-2004, 08:50 AM
  5. Replies: 12
    Last Post: 05-17-2003, 05:58 AM