用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("请先选择需要监控的文件夹!"));
} 展开
关键代码如下:
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("请先选择需要监控的文件夹!"));
} 展开
1个回答
展开全部
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 先返回,对话框才真正被销毁。
{
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 先返回,对话框才真正被销毁。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询