用AfxBeginThread创建线程出错,直接调用函数却正常,怎么回事?!

我用AfxBeginThread创建一个线程,编译通过但运行出错,把它改成直接调用函数却可以正常运行,请问这是怎么回事?关键代码如下:voidCDirWatcherDlg... 我用AfxBeginThread创建一个线程,编译通过但运行出错,把它改成直接调用函数却可以正常运行,请问这是怎么回事?
关键代码如下:

void CDirWatcherDlg::OnBnClickedButtonStart()
{
Params p;
p.m_dir=m_dir;
p.m_list=&m_list;
CWinThread *MyThread = AfxBeginThread(WatchThread,&p); //出错
//WatchThread(&p); //换成这条语句就正常运行
}

UINT WatchThread(LPVOID lpParam)
{

Params* pi = (Params*)lpParam;

// 文件夹地址不为空
if (pi->m_dir!=""){

char notify[1024];
DWORD cbBytes;

FILE_NOTIFY_INFORMATION *pnotify=(FILE_NOTIFY_INFORMATION *)notify;

HANDLE hDir = CreateFile( pi->m_dir,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);

if (hDir == INVALID_HANDLE_VALUE){
AfxMessageBox(_T("打开文件夹失败!"));
return 0;
}

while (TRUE)
{
if(ReadDirectoryChangesW(hDir, ¬ify, sizeof(notify),
TRUE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SECURITY | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE ,
&cbBytes, NULL, NULL))
{

switch(pnotify->Action)
{
case FILE_ACTION_ADDED:

AfxMessageBox(_T("Directory/File added (添加文件)- \r\n"));
break;
case FILE_ACTION_REMOVED:
AfxMessageBox(_T("Directory/File removed (删除文件)- \r\n"));
break;
case FILE_ACTION_MODIFIED:
AfxMessageBox(_T("Directory/File modified (修改文件内容)- \r\n"));
break;
case FILE_ACTION_RENAMED_OLD_NAME:
AfxMessageBox(_T("Directory/File old name (修改文件名字)- \r\n"));
break;
case FILE_ACTION_RENAMED_NEW_NAME:
AfxMessageBox(_T("Directory/File new name - \r\n"));
break;
default:
break;
}

}
}

}else
AfxMessageBox(_T("请先选择需要监控的文件夹!"));
}
展开
 我来答
silvergingko
2011-10-03 · TA获得超过5945个赞
知道小有建树答主
回答量:688
采纳率:0%
帮助的人:848万
展开全部
void CDirWatcherDlg::OnBnClickedButtonStart()
{
Params p;
...
}
这里的 p 是个局部变量,当最后调用
CWinThread *MyThread = AfxBeginThread(WatchThread,&p);
后,OnBnClickedButtonStart 函数返回,此时的状况是:
1 p 局部变量被销毁;
2 WatchThread 线程可能还工作着,且它去访问 pi 时,由于 pi 指向的是 p 这个局部变量,将可能导致访问违例,原因是 p 已经被销毁。

解决:
void CDirWatcherDlg::OnBnClickedButtonStart()
{
Params* pParams = new Params;
...
CWinThread *MyThread = AfxBeginThread(WatchThread,pParams);
}

UINT WatchThread(LPVOID lpParam)
{
Params* pi = (Params*)lpParam;
...
delete pi;
}

这种方法编码简单,但问题是 pPararms 是 new 出来的,每点击按钮一次,就会 new 一次,会导致平凡分配销毁堆内存,产生内存碎片。
还有种办法是定义 class CDirWatcherDlg { Params m_p;... }; 类变量,然后:
void CDirWatcherDlg::OnBnClickedButtonStart()
{
...
CWinThread *MyThread = AfxBeginThread(WatchThread,&m_p);
}
当然这种方法的问题是,在对话框关闭之前一定要保证 WatchThread 已经停止。因为对话框被关闭了,通常 CDirWatcherDlg 这个类实例就会被销毁了,这要看整个程序结构。但好的方法是:对话框被关闭时,不让对话框关闭,加一个同步机制,保证 WatchThread 先返回,对话框才真正被销毁。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式