比如我现在写一个多线程下载程序,包含DownloadTask、HttpDownload两个类。
class DownloadTask { //省略n行代码 public:
int m_threads;//需创建的线程总数 CCriticalSection m_cs;//临界区
void Stop(); }; class HttpDownload { //省略n行代码
HttpDownload(DownloadTask* task): m_task(task) { } public:
DownloadTask* m_task; void Start();//开始下载 }
每一个HttpDownload对象都是一个线程的执行单元,同一个任务下的所有线程共享同一个DownloadTask对象中的所有资源。如果这样编写下载程序:
//在某一个函数中 { DownloadTask* myTask = new DownloadTask() HttpDownload* download = new HttpDownload(myTask); for(int i = 0; i < myTask->m_threads; ++i) AfxBeginThread(downloadThreadFun, download); return 0; } UINT downloadThreadFun(LPVOID lParam) { auto_ptr<HttpDownload> pDownload((HttpDownload*)lParam); pDownload->Start(); return 0; }
void SetStop(DownloadTask* task)
{
task->Stop();
delete task;
}
在某一时刻,比如用户点击停止下载时,我们就需要delete掉这个DownloadTask对象。但是如果当前还有线程在运行,这样delete掉就会影响这些线程,直接导致程序出错。
所以,必须在delete DownloadTask对象前确定此下载任务中所有线程已经停止。于是可以这样写:
class DownloadTask { //省略n行代码 public: int m_threads;//需要创建的线程总数 CCriticalSection m_cs;//临界区 int m_currentThreads;//当前运行的线程数 void Stop(); }; UINT downloadThreadFun(LPVOID lParam) { auto_ptr<HttpDownload> pDownload((HttpDownload*)lParam); CSingleLock singleLock(&pDownload->m_task->m_cs); pDownload->Start(); singleLock.Lock() --pDownload->m_task->m_currentThreads; return 0; } void SetStop(DownloadTask* task) { CSingleLock singleLock(&task->m_cs); task->Stop(); singleLock.Lock(); if(task->m_currentThreads == 0) delete task; return 0; }
这样就保证在所有线程已经结束时才delete掉这个任务的DownloadTask对象。