调用创建线程函数时出现'CreateThread' : cannot convert parameter 3 from 'unsigned long (void *)' to 'unsigned lo

本文介绍了解决C++中特定情况下线程函数调用问题的方法:通过将线程函数设置为静态函数,实现无需对象即可调用的目的。

'CreateThread' 函数是C...Dlg类里的成员函数,在调用该函数的时候需要C...Dlg类的对象来调用,但是在调用该函数时又不知道用哪一个对象去调用,所以解决该问题时,只需要把C...Dlg类里的线程函数设置成静态就可以了,static....,因为静态函数是不需要对象就能调用的。ok!

<think>我们遇到的问题是在MFC中,当我们尝试将一个类的成员函数作为线程函数传递给AfxBeginThread,编译器报错:&#39;AfxBeginThread&#39; : none of the 2 overloads can convert parameter 1 from type &#39;unsigned int (void *)&#39;。这是因为类的成员函数有一个隐含的this指针参数,所以其类型与全局函数或静态成员函数的类型不同,而AfxBeginThread要求线程函数是全局函数或静态成员函数。 根据引用[2]中的讨论,用户希望将线程函数封装在类内部,但遇到了类型不匹配的问题。解决这个问题的关键是将成员函数转换为符合AfxBeginThread要求的函数类型。有两种常用方法: 方法1:将线程函数声明为静态成员函数(static) 静态成员函数没有this指针,因此其类型与全局函数相同。但是,静态成员函数不能直接访问非静态成员,所以我们需要通过参数传递this指针,然后在函数内部通过this指针来访问对象成员。 方法2:使用友元全局函数(但这样会破坏封装性,一般不推荐) 这里我们使用方法1,并给出示例代码: 步骤: 1. 在类中声明一个静态成员函数作为线程函数。 2. 将对象的指针(this)作为参数传递给线程函数(通过AfxBeginThread的参数)。 3. 在线程函数内部,将参数转换为类指针,然后通过该指针调用非静态成员函数(实际执行任务的函数)。 示例代码: ```cpp // RealtimeTask.h class CRealtimeTask { public: BOOL StartTask(); private: static UINT taskmain(LPVOID pParam); // 静态成员函数 UINT RealTask(); // 实际执行任务的非静态成员函数 }; // RealtimeTask.cpp BOOL CRealtimeTask::StartTask() { // 启动线程,将this指针作为参数传递 CWinThread* pThread = AfxBeginThread(taskmain, this); return (pThread != NULL); } UINT CRealtimeTask::taskmain(LPVOID pParam) { // 将参数转换为类指针 CRealtimeTask* pThis = (CRealtimeTask*)pParam; // 调用实际的任务函数 return pThis->RealTask(); } UINT CRealtimeTask::RealTask() { // 这里写具体的线程任务代码 for (int i = 0; i < 10; i++) { TRACE("Working... %d\n", i); Sleep(1000); } return 0; } ``` 这样,我们就将线程函数封装在类内部了。注意,在静态成员函数taskmain中,我们通过传递进来的this指针来调用非静态成员函数RealTask,从而可以访问类的非静态成员。 另外,引用[4]中提到的问题也是类似的,即无法直接传递成员函数CreateThread,因为CreateThread同样要求线程函数是全局函数或静态成员函数。解决方法同上。 总结:在MFC中,使用AfxBeginThread创建线程线程函数必须是全局函数或静态成员函数。如果希望使用类的成员函数,需要将其声明为静态,并通过参数传递对象指针(this)来访问对象成员。 引用[1]的错误就是由于传递了一个非静态成员函数导致的,因为非静态成员函数的类型是`unsigned int (类名::*)(void*)`,而AfxBeginThread要求的是`unsigned int (*)(void*)`(全局函数)或`unsigned int (__cdecl *)(void*)`(静态成员函数)。 因此,通过将成员函数改为静态,并传递this指针,即可解决该问题。 相关问题: 1. 如何在MFC中安全地终止一个线程? 2. MFC中工作线程如何向主线程发送消息? 3. 在多线程编程中,如何避免资源竞争?</think>### 解决 VC6.0 MFC 线程创建错误:&#39;none of the 2 overloads can convert parameter 1&#39; #### 问题分析 错误 `error C2665: &#39;AfxBeginThread&#39; : none of the 2 overloads can convert parameter 1 from type &#39;unsigned int (void *)&#39;` 的根本原因是:**类的非静态成员函数有隐藏的 `this` 指针参数**,导致其函数签名与 `AfxBeginThread` 要求的线程函数类型不匹配[^2]。具体来说: 1. 非静态成员函数的实际类型是:`unsigned int (ClassName::*)(void*)` 2. `AfxBeginThread` 要求的是:`unsigned int (*)(void*)`(全局函数)或 `static unsigned int (*)(void*)`(静态函数) #### 解决方案 以下是三种有效解决方法: ##### 方法1:使用静态成员函数(推荐) ```cpp // MyClass.h class CMyClass { public: BOOL StartThread(); private: static UINT ThreadProc(LPVOID pParam); // 静态成员函数 UINT RealThreadWork(); // 实际执行任务的非静态函数 }; // MyClass.cpp BOOL CMyClass::StartThread() { // 传递this指针作为参数 AfxBeginThread(ThreadProc, this); // ✅ 正确匹配 return TRUE; } UINT CMyClass::ThreadProc(LPVOID pParam) { // 将参数转换为类指针 CMyClass* pThis = (CMyClass*)pParam; return pThis->RealThreadWork(); // 调用实际任务 } UINT CMyClass::RealThreadWork() { // 实际线程任务代码 for(int i=0; i<10; i++) { TRACE("Working...%d\n", i); Sleep(1000); } return 0; } ``` ##### 方法2:使用全局函数包装器 ```cpp // 全局函数包装器 UINT GlobalThreadWrapper(LPVOID pParam) { CMyClass* pObj = (CMyClass*)pParam; return pObj->MemberThreadFunc(); // 调用成员函数 } // 类成员函数 UINT CMyClass::MemberThreadFunc() { /* 实际任务 */ } // 启动线程 void CMyClass::StartThread() { AfxBeginThread(GlobalThreadWrapper, this); // ✅ } ``` ##### 方法3:使用 `_beginthreadex` 替代 ```cpp #include <process.h> unsigned __stdcall ThreadProc(void* pParam) { CMyClass* pThis = (CMyClass*)pParam; return pThis->DoWork(); } void CMyClass::StartThread() { _beginthreadex(NULL, 0, ThreadProc, this, 0, NULL); // ✅ } ``` #### 关键区别解析 | 函数类型 | 实际签名 | 是否可用作线程函数 | |------------------------|----------------------------------|-------------------| | 全局函数 | `UINT (*)(LPVOID)` | ✅ 是 | | **静态成员函数** | `UINT (*)(LPVOID)` | ✅ 是 | | 非静态成员函数 | `UINT (ClassName::*)(LPVOID)` | ❌ 否 | #### 注意事项 1. **资源管理**:通过 `this` 指针访问对象,需确保对象生命周期覆盖线程执行期 2. **线程安全**:使用 `CCriticalSection` 保护共享数据 ```cpp CCriticalSection m_cs; void UpdateData() { CSingleLock lock(&m_cs, TRUE); // 自动加锁 // 操作共享数据... } // 自动解锁 ``` 3. **MFC对象访问**:工作线程中更新UI需用 `PostMessage` 而非直接操作控件[^3] #### 错误示例分析 ```cpp class CRealtimeTask { public: UINT taskmain(LPVOID param); // ❌ 非静态成员 BOOL StartTask() { AfxBeginThread(taskmain, NULL); // 触发编译错误 } }; ``` 此代码会触发所述错误,因 `taskmain` 实际类型为 `unsigned int (CRealtimeTask::*)(void*)`,不符合要求[^2]。 #### 相关问题 1. 如何在MFC线程间安全传递复杂数据结构? 2. 工作线程如何安全更新MFC界面控件? 3. 如何正确终止MFC工作线程并释放资源? 4. MFC界面线程与工作线程的性能差异有哪些? 5. 在多线程程序中如何避免死锁和资源竞争?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值