VC,Windows编程心得

结束了一周的工作,好好总结一下!

 

    关于MFC的线程

    

    由于需要做文件上传的工作,起初做的对话框很死板,只是单纯的使用主线程直接执行上传文件的操作,上传过程中界面卡在哪里,虽然是模态窗口,但让人感觉很不友好,并且界面非常不友好,所以就决定另外开一个线程来执行上传的操作,并美化界面。

 

    在做了必要的验证之后,便开始编写线程。主要的思路是,在用户点击上传按钮以后,便开启一个工作线程UplaodTthread(working thread),并做好对话框中对应控件的控制(如隐藏、disable等操作)。然后在UplaodTthread中执行上传的操作。

 

    原本以为这样就可以了,但突然想到用户是可以取消的,于是决定加上取消的操作。于是问题就来了,如果取消,必定是要终止上传的线程UplaodTthread,如何终止线程又成了个问题,这就涉及到线程同步的问题。在这里实在花了一点时间,网上说法一大堆,用MFC类的,用win32函数的,都试了试,也许我还理解的不透彻,所以都失败,最后就直接用了最原始的方法去同步线程——直接使用公共变量来实现线程之间的同步。

    

    在UplaodTthread中使用设置一个标志bool值,用户在主线程发出了终止上传的消息,开启另一个线程UploadAbortedThread线程,在次线程中改变这个值,就可以让UploadThread的上传过程终止,也就是让UploadThread这个working thread直接返回,上传线程终止。而此时,并不能直接关闭对话框,因为UploadThread是需要用到对话框里面的资源的,所以在UploadAbortedThread中还要判断另一个标志bool值,判断UploadThread是否已经返回,UploadThread在return之前改变这个标志bool值(严格的说,这是不严谨的,因为执行这两个指令是可能被打断的,但考虑到return指令不涉及任何其他资源的引用,而且工作线程是全局函数,所以我个人觉得是可以忽略),UploadAbortedThread得知之后,便发送消息,对话框拦截消息,对话框关闭。

 

    这里主要技术点是在创建MFC线程和线程之间的通信,以及工作线程和主线程之间的通信。

    工作线程之间的通信:如前所述,我采用的方法是让这两个线程使用同一个对话框里面的同一个变量(比较原始,也许有更好的方法)。

    工作线程与主线程之间的通信:AfxBeginThread(FileUploadAbortedThread,this)。由于是主线程(对话框)开启的线程,所以可以把对话框的指针(this)传递给工作线程,工作线程中队指针进行转换,于是就可以获得对话框对象中的所有公有成员函数以及变量。

    如何使工作线程的行为影响到主线程:使用cwnd::PostMessage,在本例中,因为工作线程已经获得了对话框的指针,于是就可以使用pCDialog->PostMessage(WM_USER_DEFINE_MSG),对话框自己拦截捕获这个消息,处理消息。在本例中,对话框的关闭,都是使用这种方法,工作线程发送消息,主线程(对话框)截获,做收尾工作,然后关闭对话框。

    当然,这里也涉及到自定义消息和在MFC中消息传递路径,把自定义消息放到消息队列中的宏是:

    ON_MESSAGE(WM_USER_DEFINE_MSG, pFunc)

    WM_USER_DEFINE_MSG 一般的定义是 #define WM_UPLOA_FILE_OK (WM_USER + 101)

    消息函数的声明:

    afx_msg LRESULT OnUploadAborted(WPARAM wParam, LPARAM lParam);

    至于MFC消息的传递路径,这就和MFC框架有关了,由于在本例中是由对话框对象发送的消息,所以,此对话框类只要有对自定义消息的拦截(也就是在此对话框类中插入了消息映射宏),就会首先截获消息,然后处理消息。

 

    关于CFileDialog类

   文件上传,必然要支持多选,即一次上传多个文件,除了在构造函数的第四个参数中指定OFN_ALLOWMULTISELECT外,所选文件的名称也是需要特殊的方法保存的,如下代码

CString csFileNameBuffer;

cf.m_ofn.lpstrFile = csFileNameBuffer.GetBuffer(NMAXFILE) ;

cf.m_ofn.nMaxFile = NMAXFILE;

其中cf就是CFileDialog的一个对象,它使用CString的一个对象来保存所选文件的所有路径,这里就体现了MFC类提供的功能,下面代码是依次获得所有文件名:

POSITION pos = cf.GetStartPosition();

for (int i = 0;pos != NULL;++i)

{

fileName = cf.GetNextPathName(pos);

}

csFileNameBuffer.ReleaseBuffer();

当然,在使用之后需要释放CString 对象所申请的空间,说明,CString对象可以动态申请空间(可是为什么不能自己在析构的时候去释放申请的空间呢?困惑~~~)

你可能感兴趣的:(VC,Windows编程心得)