对话框工程中,
为什么我在
BOOL CMain::OnInitDialog()
中这样写:
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)InitSQL,(void*)0,NULL,&nThreadID);
总出错?
UINT CMain::InitSQL(LPVOID lpVoid)
{
...
}错误信息:
Main.cpp(103):error C2440:'type cast':cannot convert from '' to 'unsigned long (__stdcall)(void *)'
None of the functions with this name in scope match the target type
再者,如果我要把一个CEdit型的变量传给InitSQL的话,在CreateThread中的那个参数应该怎么写?
为什么我在
BOOL CMain::OnInitDialog()
中这样写:
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)InitSQL,(void*)0,NULL,&nThreadID);
总出错?
UINT CMain::InitSQL(LPVOID lpVoid)
{
...
}错误信息:
Main.cpp(103):error C2440:'type cast':cannot convert from '' to 'unsigned long (__stdcall)(void *)'
None of the functions with this name in scope match the target type
再者,如果我要把一个CEdit型的变量传给InitSQL的话,在CreateThread中的那个参数应该怎么写?
如果是静态回调函数:
class CMain
{
...
CALLBACK static UINT InitSQL(LPVOID lpVoid);
...
}
如果是全局函数:
UINT InitSQL(LPVOID lpVoid)
{
}如果要把一个CEdit型的变量传给InitSQL的话,应该传CEdit的指针,这样写:
(假设pEdit是指向CEdit的指针)
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)InitSQL,(void*)pEdit,NULL,&nThreadID);
在线程函数中可以这样使用:
UINT InitSQL(LPVOID lpVoid)
{
CEdit* pEdit = (CEdit*)lpVoid;
...
}
class main:public CDialog
{
...
CALLBACK static UINT InitSQL(LPVOID lpVoid);
...
}错误信息:
warning C4518:'static':storage-class or type specifier(s) unexpected here;ignored
warning C4230:anachronism used:modifiers/qualifiers interspersed,qualifier ignored
error C2146:syntax error : missing ';' before identifier 'InitSQL'
warning C4229:anachronism used:modifiers on data are ignored后我把它改为全局可以了,不过,还没有得到完全测试
static UINT CALLBACK InitSQL(LPVOID lpVoid);
把this传给线程,但在线程里:
UINT InitSQL(LPVOID lpVoid)
{
CMain* pMain=(CMain*)lpVoid;
try
{
pMain->pConn->Open((_bstr_t)strconn,TEXT(struser),TEXT(strpw),adModeUnknown);
...
时,pMain->pConn->Open这一句出错,说是无效指针!!!
pConn是在CMain里定义的一个变量:
_ConnectionPtr pConn;
static UINT CALLBACK InitSQL(LPVOID lpVoid);
在实现里:
UINT CALLBACK CMain::InitSQL(LPVOID lpVoid)
{
CMain* pMain=(CMain*)lpVoid;
try
{
...
依然说是无效指针!(在实现函数的前边不能加static,如果加上去的话,是出错,所以我把这里的static删去了)
是这样调用的:
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)InitSQL,(void*)this,NULL,&nThreadID);
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)CMain::InitSQL,(void*)this,NULL,&nThreadID);
...
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)CMain::InitSQL,(void*)this,NULL,&nThreadID); return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}UINT CALLBACK CMain::InitSQL(LPVOID lpVoid)
{
CMain* pMain=(CMain*)lpVoid;
try
{
pMain->pConn->Open((_bstr_t)strconn,TEXT(struser),TEXT(strpw),adModeUnknown);//这一句出错,无效指针 CString strsql="select * from storage order by prod_name,prod_spec";
//_ConnectionPtr pConn;
pMain->pRec->Open(_variant_t(strsql),_variant_t((IDispatch*)pMain->pConn,true),adOpenStatic,adLockOptimistic,adCmdUnknown);
//pRec->Open((LPCTSTR)strsql,(LPCTSTR)strconn,adOpenStatic,adLockOptimistic,adCmdUnknown);
pMain->m_btnadd.EnableWindow(true);
pMain->m_btnlook.EnableWindow(true);
}
catch(_com_error e)
{
::MessageBox(pMain->m_hWnd,e.ErrorMessage(),TEXT("错误01"),MB_ICONSTOP);
}
pMain->m_btnexit.EnableWindow(true); return 0;
}
把下面的pMain改成this就可以了!
UINT CALLBACK CMain::InitSQL(LPVOID lpVoid)
{
try
{
pMain->pConn->Open((_bstr_t)strconn,TEXT(struser),TEXT(strpw),adModeUnknown);//这一句出错,无效指针 CString strsql="select * from storage order by prod_name,prod_spec";
//_ConnectionPtr pConn;
pMain->pRec->Open(_variant_t(strsql),_variant_t((IDispatch*)pMain->pConn,true),adOpenStatic,adLockOptimistic,adCmdUnknown);
//pRec->Open((LPCTSTR)strsql,(LPCTSTR)strconn,adOpenStatic,adLockOptimistic,adCmdUnknown);
pMain->m_btnadd.EnableWindow(true);
pMain->m_btnlook.EnableWindow(true);
}
catch(_com_error e)
{
::MessageBox(pMain->m_hWnd,e.ErrorMessage(),TEXT("错误01"),MB_ICONSTOP);
}
pMain->m_btnexit.EnableWindow(true); return 0;
}
#include <iostream.h>
#include <windows.h>
class myclass
{
private:
static int num;
public:
static UINT threadfunc(LPVOID lp);
void set(int num1){num = num1;};
};
int myclass::num = 9;
UINT myclass::threadfunc(LPVOID lp)
{
num ++;
cout<<"hello world "<<num<<endl;
return 0;
}
void main()
{
myclass a;
a.set(3);
unsigned long nThreadID;
HANDLE handle=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)myclass::threadfunc,(void*)0,NULL,&nThreadID);
WaitForSingleObject(handle,INFINITE);
}
如果想把CEdit 对象a传进去就在CreateThread的第4个参数为(LPVOID)&a.就可以了,在线程里面自己在给他还原回来了。
我把pMain去掉,也出错,就是那些变量没有生命开始的时候,我也认为是在同一个类里边就不需要再传指针了,就可以直接使用这是了,但结果却是不行的,
真是,入门咋就这么难呢?
{
CMyObject* pObject = (CMyObject*)pParam; if (pObject == NULL ||
!pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
return 1; // if pObject is not valid // do something with 'pObject' return 0; // thread completed successfully
}// inside a different function in the program
.
.
.
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);
.this is a example from MSDN.
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)CMain::InitSQL,(void*)this,NULL,&nThreadID);
这是不是在CMain中调用的。
还有我还没搞懂到底谁是无效指针pMain or pConn,
如果是在不行就把线程中要用的变量全部申明成全局的
如果线程A给线程B传递了一个CWnd指针而线程B要调用CWnd对象的成员函数,那么MFC在调试状态下会出现断言错误.(MFC Windows程序设计 Jeff Prosise)
主要是因为句柄映射表对于每个线程都是本地使用的,在其他线程中不可见.如果线程A创建了CWnd,它的地址传递给了ASSERT_VALID,但是相应的HWND却不会在线程B的永久或临时的句柄映射表中出现,就会出现断言错误.
可以通过传递真实的句柄而非对象的指针来避免断言处理发生.
原来我在调用pConn.CreateInstance("ADODB.Connection");和pRec.CreateInstance("ADODB.Recordset");时,还没有调用那个AfxOleInit(),而是在调用CreateInstance之后才调用AfxOleInit();,所以说无效指针原来是指pConn,可我一直竟把pMain当成了无效指针,好傻,我
另外,在OnInitDialog里已经调用过了AfxOleInit,但到了线程中还需要调用AfxOleInit