C Board  

Go Back   C Board > Platform Specific Boards > Windows Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 01-13-2007, 06:45 PM   #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-
WaterNut is offline   Reply With Quote
Old 01-13-2007, 06:58 PM   #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?????
WaterNut is offline   Reply With Quote
Old 01-13-2007, 07:23 PM   #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()?
WaterNut is offline   Reply With Quote
Old 01-13-2007, 08:22 PM   #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.
WaterNut is offline   Reply With Quote
Old 01-13-2007, 11:59 PM   #5
CSharpener
 
vart's Avatar
 
Join Date: Oct 2006
Posts: 5,336
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
__________________
If I have eight hours for cutting wood, I spend six sharpening my axe.
vart is offline   Reply With Quote
Old 01-14-2007, 01:58 AM   #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.
__________________
Enlighten Yourself

I'm back!
Wraithan is offline   Reply With Quote
Old 01-15-2007, 08:17 PM   #7
Registered User
 
Join Date: May 2004
Posts: 164
Vart,
thanks for helpful reply, I appreciate your assistance as always that helps.
WaterNut is offline   Reply With Quote
Old 01-15-2007, 08:39 PM   #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 -
WaterNut is offline   Reply With Quote
Old 01-15-2007, 09:47 PM   #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.....
WaterNut is offline   Reply With Quote
Old 01-15-2007, 09:57 PM   #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.....
WaterNut is offline   Reply With Quote
Old 01-16-2007, 03:41 AM   #11
Cat without Hat
 
CornedBee's Avatar
 
Join Date: Apr 2003
Posts: 8,492
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
CornedBee is offline   Reply With Quote
Old 01-16-2007, 10:10 AM   #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....
WaterNut is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
multithreading in c thebrighter C Programming 8 07-10-2007 01:17 PM
call webbrowser.Navigate within a thread via post message to UI thread hanhao Windows Programming 2 07-01-2007 07:11 AM
multithreading question ichijoji C++ Programming 7 04-12-2005 10:59 PM
Win32 Thread Object Model Revisted Codeplug Windows Programming 5 12-15-2004 08:50 AM
injecting my own thread into the address space of another process - cannot call any f Andrew_5342 Windows Programming 12 05-17-2003 05:58 AM


All times are GMT -6. The time now is 01:14 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22