author: scruffybear

release time: 08/01/2007

company: Watchdata  

如有转载,请注明出处,并保持文章的完整性,谢谢!     

      前两个月写了一个读写卡片中文件的一个小程序,对卡片中的一个文件进行读写十万次,以检测卡片读写文件的寿命是否达到要求。用VC.net进行编写,由于读写卡片的驱动已经写好了,所以只需要对动态库中的函数进行调用就可以了。完成了也没有碰到太大的困难。但是有一个问题还没有解决,由于循环读写十万次,运行时程序界面会出现假死的情况,但是界面上要实时显示当前时刻执行了读写次数。也就是说在程序运行的时候不能碰界面,如果用鼠标点击界面,界面立刻就不动了。问题不是致命的,但是也让人觉得很厌烦,花了点时间把它给解决了,解决的方法是采用多线程。创建一个新的线程,将十万次读写放在这个新线程中执行,这样主线程就有机会响应界面了。解决问题方法如下(针对本程序):

1,定义全局线程函数。
  在CfielreadandwriteDlg界面类中定义如下函数定义:
  friend void Proc_WR(LPVOID param);
  十万次循环程序会放在这个函数中。一般来说,C++的类成员函数不能作为线程函数。这是因为在类中定义的成员函数,编译器会给其加上this指针。编译时会报如下错误:
  error C2664: cannot convert parameter 1 from 'void (void *)' to 'void(__cdecl *)(void *)'
  解决方法有两种:一就是将该成员函数声明为static类型,去掉this指针;另一种是不定义类成员函数为线程函数,而将线程函数定义为类的友元函数。这样,线程函数也可以有类成员函数同等的权限。本文采用第二种方法。

2,编写全局线程函数。
  在函数void Proc_WR(LPVOID param)的第一行写入以下代码处理传入的参数LPVOID param:
  CfielreadandwriteDlg * pTaskMain = (CfielreadandwriteDlg *) param;
  这样就可以通过pTaskMain指针访问CfielreadandwriteDlg类中的成员变量和成员函数。
  在这句话后面加上卡片十万次读写程序。

3,在主线程处创建新线程。
  本文中是在点击执行按钮会创建此新线程执行十万次读写。在以下程序中加入代码:
 

void CfielreadandwriteDlg::Begin_Clicked()
 {
_beginthread(Proc_WR,0,this);
 }
 其中要加上#include <process.h>头。
 _beginthread的函数原型如下:
 uintptr_t _beginthread(
 void( __cdecl *start_address )( void * ), //Start address of routine that begin execution of new thread
 unsigned stack_size, //Stack size for new thread or 0.
 void *arglist //Argument list to be passed to new thread or NULL
);


  最后的参数是传入的参数,也就是CfielreadandwriteDlg的指针,这样就可以访问CfielreadandwriteDlg类的资源了。

4,注意事项
  最开始调试的时候会出现以下错误:
error C3861: '_beginthreadex': identifier not found, even with argument-dependent lookup
  明明是加入了#include <process.h>,却会出现这个错误。在网上搜索,这个问题还真不好找,最后在国外的一个站点得到解答,如下:
   To build a multithread application you must tell the compiler to use a special version of the libraries (LIBCMT.LIB). To select these libraries, first open the project's Property Pages dialog box (View menu) and click the C/C++ folder. Select the Code Generation page. From the Runtime Library drop-down box, select Multi-threaded. Click OK to return to editing.
or add /MT to the command line of your compiler.

  原来是运行多线程程序需要在编译的时候在相应的地方进行设置以告诉编译器这是一个多线程的程序,否则会出现以上错误。

  另外如果使用CreateThread创建线程,则不能进行以上设置,否则会出现以下错误,不知道是不是这个原因:
  threadC error LNK2001: unresolved external symbol __malloc_dbg
  原因还未知,有时候会有莫名其妙的错误。没办法。

  在VC工程中添加C代码时有时候会出现以下错误:
    fatal error C1010: unexpected end of file while looking for precompiled header directive
   原因是发生错误的文件是由其他的C代码文件添加进入当前工程而引起的,则Alt+F7进入当前工程的 Settings,选择C/C++选项卡,从Category组合框中选中Precompiled Headers,选择Not Using Precompiled headers。确定。

以下几个网址的资料比较经典:
​​​http://www.java-asp.net/vc/200510/t_411.html​​​
​​​http://www.bjx.com.cn/files/wx/dzjxgc/2003-1/13.htm​