多线程CString参数传递问题

代码如下:

   1: void CallThreadFun()
   2: {
   3:     CString strPath="C:\\a.txt";
   4:     HANDLE hThread=::CreateThread(NULL,NULL,ThreadFunc,(LPVOID)(LPCTSTR)str,0,&thID);
   5:     CloseHandle(hThread);    
   6: }
   7:  
   8: DWORD WINAPI ThreadFunc(LPVOID lpParam)
   9: {
  10:     CString strPath=(LPCWSTR)lpParam;
  11:     doSomething(strPath);
  12:     ....
  13: }

1.

strPath参数总是传不过去

单步跟踪到Line 10,发现CString strPath=(LPCWSTR)lpParam;strPath里没有值,CreateThread()函数参数是传地址方式,说明地址没有传过去,后来百度一下,发现如下:

image

我在CallThreadFun函数中定义的strPath变量时局部变量,在改函数执行玩,strPath变量所占内存便释放了,所以在线程函数ThreadFunc()中,strPath值是无法通过地址传递过去的,因为对象已经析构了。

解决办法:

1)将CallThreadFun函数中的strPath变量设成全局变量

2)将CallThreadFun函数中的strPath变量设成静态局部变量

3)在CreateThread调用下加一句WaitForSingleObject(hThread,INFINITE);不过这样似乎失去了多线程异步执行效率高的意义了。不过,需要线程同步的话就另当别论了。

4).CString *strPath= new CString(“C:\\a.txt”);在堆上分配内存,记住用完要delete。

以上两种办法都能保持程序在运行期间strPath变量一直存储在内存中,所以在ThreadFunc()函数中lpParam变量是可寻址的。

2.

关于CString转换成LPCTSTR问题。

MSDN原话如下:

--------------------------------------------------------------------------------------------------------------------------

CString objects also have the following characteristics:

  • CString objects can grow as a result of concatenation operations.
  • CString objects follow “value semantics.” Think of a CString object as an actual string, not as a pointer to a string.
  • You can freely substitute CString objects for const char* and LPCTSTR function arguments.
  • A conversion operator gives direct access to the string’s characters as a read-only array of characters (a C-style string).

Tip   Where possible, allocate CString objects on the frame rather than on the heap. This saves memory and simplifies parameter passing.

--------------------------------------------------------------------------------------------------------------------------

msdn说你可以自由转换CString对象为const char *和LPCTSTR类型。以下是几种传参方法。

1):使用上述转换法:

   1: void CallThreadFun()
   2: {
   3:     static CString strPath="C:\\a.txt"; 
   4:     HANDLE hThread=::CreateThread(NULL,NULL,runBatFile,(LPVOID)(LPCTSTR)strPath,0,&thID);
   5:     …… 
   6: }
   7:  
   8: DWORD WINAPI ThreadFunc(LPVOID lpParam)
   9: {
  10:      CString strPath=(LPCWSTR)lpParam;
  11:       ....
  12: }
  13:  

2):&取地址传参

   1: void CallThreadFun()
   2: {
   3:     static CString strPath="C:\\a.txt";  
   4:     HANDLE hThread=::CreateThread(NULL,NULL,runBatFile,&strPath,0,&thID);
   5:     …… 
   6: }
   7:  
   8: DWORD WINAPI ThreadFunc(LPVOID lpParam)
   9: {
  10:      CString pp=*((CString *)lpParam);
  11:      ....
  12: }

注意:&strPath 和strPath.GetBuffer()的地址是不一样的。不能用strPath.GetBuffer()返回的地址传参,传递了以后无法解引用!

3):new 动态分配内存

   1: void CallThreadFun()
   2: {
   3:     CString *strPath=new CString("C:\\a.txt");  
   4:     HANDLE hThread=::CreateThread(NULL,NULL,runBatFile,strPath,0,&thID);
   5:     …… 
   6:     strPath=NULL;
   7: }
   8:  
   9: DWORD WINAPI ThreadFunc(LPVOID lpParam)
  10: {
  11:      CString *lpPath=((CString *)lpParam);
  12:      ....
  13:      delete lpPath;
  14: }

你可能感兴趣的:(String)