武警吉林省总队新兵:多线程访问文件问题中WaitForSingleObject方法的使用,及其效率!_FULL...

来源:百度文库 编辑:偶看新闻 时间:2024/05/06 05:15:11
多线程访问文件问题中WaitForSingleObject方法的使用,及其效率!2007年09月27日 星期四 16:35

//多线程读取文件,同时把读取到的文件内容再用多线程写入到指定的空白文件中,实现多线程读写文件

//从程序中可以看到使用WaitForSingleObject()函数。来控制多线程访问同一文件时不至于发生冲突。通过CEvent g_fileReadEvent, g_fileWriteEvent;这两个变量的ResetEvent()函数和SetEvent()函数来设置信号量的nonsignaled和signaled状态。其用法可以看下文红色字迹所示

struct filePart
{
int nBegin;
int nCur;      // 文件指针现在的位置,用于读取
int nPre;      // 文件指针原先的位置,用于写入
int nEnd;

CWinThread * pThread; // 记录线程活动情况
};

CEvent g_fileReadEvent, g_fileWriteEvent;


bool DealFileThread(CString fileName, filePart * pFilePart_STR) //随便写个函数说明
{
FILE *file;
int readLen ;

//MAX_BUFFER_LEN 在头文件里定义,这里能够保证数据不丢失,也不至于内存逸出
char *buffer = new char[MAX_BUFFER_LEN];

while (pFilePart_STR->nCur < pFilePart_STR->nEnd)      // 线程没有完成自己的模块就不能退出
{
  WaitForSingleObject(g_fileReadEvent, INFINITE);      // nonsignaled就等,在线程运行之前,先调用 g_fileReadEvent.SetEvent();和 g_fileWriteEvent.SetEvent();使该信号量处在signaled状态。
   g_fileReadEvent.ResetEvent();      // 设为nonsignaled状态,这时其它的线程已经不能访问文件了,只有等待,而且是不耗资源的等待。
       file = fopen(fileName,"r+b");
       if (NULL != fpThreadLog)
       {
        fprintf(fpThreadLog, "thread %d writing\n", pFilePart_STR->pThread->m_nThreadID);
       }

       if(file == NULL)
        return false;
   
// SEEK_CUR//:Current position of file pointer
// SEEK_END//:End of file
// SEEK_SET//:Beginning of file

       fseek(file, pFilePart_STR->nCur, SEEK_SET/*从开头开始读取文件*/);      // 指针到该线程读取文件块位置的开头,准备读取文件

       readLen = fread(buffer, sizeof(char), MAX_BUFFER_LEN, file);// 读取该位置文件的二进制内容
       pFilePart_STR->nPre = pFilePart_STR->nCur;         // 现在指针的位置已经变了,所以记录到前一个位置上
       pFilePart_STR->nCur = ftell(file);           // 记录现在文件指针的位置
   
       fclose(file);      //释放资源
   
   g_fileReadEvent.SetEvent();      // 设为signaled状态,对文件的读取操作完成后,设置信号量为singaled状态,让其它线程能访问已经释放的资源。


     WaitForSingleObject(g_fileWriteEvent, INFINITE);

     g_fileWriteEvent.ResetEvent();
         FILE *fpToWrite = fopen(strToWrite, "r+b");       // 打开待写文件
     
         if (NULL == fpToWrite)
         {
          return false;
         }

         fseek(fpToWrite, pFilePart_STR->nPre, SEEK_SET); // 在刚才记录二进制内容的文件位置上写入
         fwrite(buffer, sizeof(char), MAX_BUFFER_LEN, fpToWrite); // 写二进制内容
         fclose(fpToWrite);
     
     g_fileWriteEvent.SetEvent();
     
}

delete[] buffer;        // 释放空间
return true;
}

通过实验可以看出,WaitForSingleObject方法的效率确实很高!