这是一个多线程日志的最简单的全局函数,
g_logsec为全局变量
void WriteToLog(CString strLog, CString strFileName)
{
int j = 0;
EnterCriticalSection(&g_logsec); DWORD dwAttr;
CString str;
CTime t=CTime::GetCurrentTime ();
str=t.Format ("%Y-%m-%d %H:%M:%S    ");
str = str+strLog+"\r\n"; dwAttr=GetFileAttributes(strFileName);
if(dwAttr==0xFFFFFFFF)//如果该文件不存在就创建一个
{
CStdioFile file;
file.Open(strFileName,CFile::modeCreate|CFile::modeWrite);
file.Close();
}
CStdioFile file;
file.Open(strFileName,CFile::modeWrite);
file.SeekToEnd();
file.WriteString(str);
file.Close();

LeaveCriticalSection(&g_logsec);
return;
}我用的时候出现了一个很奇怪的问题,我跟踪发现入口参数strLog每次都很正确,
也很顺利的EnterCriticalSection,也很顺利的执行file.WriteString(str);
看样子一切都没错,但文本文件中死活就没写进去的内容为了方便大家帮我解决,我把相关现象描述清楚
1.我写的是一个MFC程序,在MFC程序的OnInitDialog中第一次调用WriteToLog总是对的,每次内容都写进去了
2.程序起来后,我界面中有个按钮,一点就启动了一个workthread,然而在workthread的函数中就出现写不进日志的情况了
3.workthread函数的主要功能是从sql server读到数据,然后写入日志
4.如果数据库中有数据,我点按钮启动workthread,写日志没问题,如果数据库没数据,我启动workthread后,再在数据库添加数据就发现workthread的写日志就写不进去了
5.我把多线程日志函数单独拿出来试,好象也没什么问题。
6.我自己怀疑是不是和自己的程序有关,而不是多线程日志函数的问题请大家帮帮忙

解决方案 »

  1.   

    线程函数
    其中m_accessdb是访问数据库的类对象
    CAutoOpenDlg &thisdlg = *((CAutoOpenDlg*)lpParam);
    WriteToLog( thisdlg.m_clientid + "  监控被打开","log.txt");
    CTime currtime;
    HINSTANCE hRet;
    HWND hflashwnd = NULL;
    int nEnterTimes=0;
    while(true)
    {

    if (thisdlg.m_bOpen == false)//flash 没打开,不断查询数据库
    {
    if(false == thisdlg.m_accessdb.GetFlashInfo(thisdlg.m_MsgTime,thisdlg.m_FlashPath,thisdlg.m_clientid))
    {

    WriteToLog(thisdlg.m_clientid + "  GetFlashInfo执行失败","log.txt");
    while (true)
    {
    if (true == thisdlg.m_accessdb.ConnectToDB(thisdlg.m_dbip,thisdlg.m_dbname,thisdlg.m_dbuser,thisdlg.m_dbpwd))
    {
    if (true == thisdlg.m_accessdb.GetFlashInfo(thisdlg.m_MsgTime,thisdlg.m_FlashPath,thisdlg.m_clientid))
    {
    break;
    }

    }
    else
    {
    Sleep(3000);
    }
    } }
    currtime = CTime::GetCurrentTime();

    if (currtime >= thisdlg.m_MsgTime.starttime)
    {
    if (currtime >= thisdlg.m_MsgTime.endtime)
    {
    if( false == thisdlg.m_accessdb.DeleteInfoFromDB(thisdlg.m_MsgTime.Msgid,thisdlg.m_clientid))
    {
    WriteToLog(thisdlg.m_clientid + "  DeleteInfoFromDB执行失败","log.txt");
    }
    continue;
    }
    else
    {
    //检查flash路径是否正确
    if (thisdlg.m_FlashPath == "")
    {
    WriteToLog(thisdlg.m_clientid + "  Flash路径为空","log.txt");
    continue;
    }
    thisdlg.m_FileName = thisdlg.m_FlashPath.Right((thisdlg.m_FlashPath.GetLength()-thisdlg.m_FlashPath.ReverseFind('\\') -1 ));
    thisdlg.m_FlashPath = thisdlg.m_FlashPath.Left(thisdlg.m_FlashPath.GetLength() - thisdlg.m_FileName.GetLength());
    thisdlg.m_FlashPath.Replace("\\","\\\\");
     
    hRet = ShellExecute(NULL,_T("open"),_T(thisdlg.m_FileName),NULL,_T(thisdlg.m_FlashPath),SW_SHOW); if ((int)hRet > 32)//打开成功
    {
    if(false == thisdlg.m_accessdb.UpdateFlag(thisdlg.m_MsgTime,"1",thisdlg.m_clientid))
    {
    WriteToLog(thisdlg.m_clientid + "  UpdateFlag执行失败","log.txt");
    }
    WriteToLog(thisdlg.m_clientid +"  "+ thisdlg.m_FlashPath + thisdlg.m_FileName +"被打开","log.txt");
    thisdlg.m_bOpen = true;
    if (thisdlg.m_FileName.Find("事实") == 0)
    {
    thisdlg.m_defaultspan = 10000;
    }
    else
    {   
    thisdlg.m_defaultspan = 3000;
    } //间隔一段时间找WINDOW HANDLE,发送回车消息
    if (thisdlg.m_timespanEnter > thisdlg.m_defaultspan)
    {
    Sleep(thisdlg.m_timespanEnter);
    }
    else
    {
    Sleep(thisdlg.m_defaultspan);
    }

    nEnterTimes=3;
    while (nEnterTimes > 1 )
    {
    hflashwnd = NULL;
    hflashwnd = ::FindWindow(NULL,"Macromedia Flash Player 7");
    if (NULL == hflashwnd)
    {
    hflashwnd = ::FindWindow(NULL,"Macromedia Flash Player 8");
    if (NULL == hflashwnd)
    {
    nEnterTimes--;
    WriteToLog(thisdlg.m_clientid+"  "+thisdlg.m_FlashPath + thisdlg.m_FileName+"GetWndHandle失败","log.txt");
    continue;
    }
    else
    {
    ::SetWindowPos(hflashwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
    ::SendMessage(hflashwnd,WM_KEYDOWN,VK_RETURN,0);
    ::SendMessage(hflashwnd,WM_KEYUP,VK_RETURN,0);
    break; }
    }
    else
    {
    ::SetWindowPos(hflashwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
    ::SendMessage(hflashwnd,WM_KEYDOWN,VK_RETURN,0);
    ::SendMessage(hflashwnd,WM_KEYUP,VK_RETURN,0);
    break;
    } } }
    else//打开失败
    {
    WriteToLog(thisdlg.m_clientid +"  "+ thisdlg.m_FlashPath + thisdlg.m_FileName +"打开失败","log.txt");
    } }
    }
    else//flash播出时间未到
    {
    Sleep(2000);
    }
    }
    else//m_bOpen == true  flash 打开了,要准备把它关掉 
    {
    currtime = CTime::GetCurrentTime();
    if (currtime > thisdlg.m_MsgTime.endtime)
    {
    nEnterTimes = 3;
    while ( nEnterTimes > 1 )
    {
    hflashwnd = NULL;
    hflashwnd = ::FindWindow(NULL,"Macromedia Flash Player 7");
    if (NULL == hflashwnd)
    {
    hflashwnd = ::FindWindow(NULL,"Macromedia Flash Player 8");
    if (NULL == hflashwnd)
    {
    nEnterTimes--;
    WriteToLog(thisdlg.m_clientid +"  "+ thisdlg.m_FlashPath + thisdlg.m_FileName+"GetWndHandle失败","log.txt");

    continue;
    }
    else
    {
    ::SendMessage(hflashwnd,WM_CLOSE,0,0);
    thisdlg.m_accessdb.UpdateFlag(thisdlg.m_MsgTime,"2",thisdlg.m_clientid);

    WriteToLog(thisdlg.m_clientid +"  "+ thisdlg.m_FlashPath + thisdlg.m_FileName +"被关闭","log.txt");

    thisdlg.m_bOpen = false;
    break; }
    }
    else
    {
    ::SendMessage(hflashwnd,WM_CLOSE,0,0);
    thisdlg.m_accessdb.UpdateFlag(thisdlg.m_MsgTime,"2",thisdlg.m_clientid);
    WriteToLog(thisdlg.m_clientid +"  "+thisdlg.m_FlashPath + thisdlg.m_FileName +"被关闭","log.txt");

    thisdlg.m_bOpen = false;
    break;
    } } }
    else//关闭时间未到
    {
    Sleep(100);
    } } if ( thisdlg.m_bthreadexit == true)
    {
    break;
    }
    } WriteToLog(thisdlg.m_clientid + "  监控已经退出","log.txt");
    return 0;
      

  2.   

    tomcat_jb(老猫),如果数据库表为空我不会调用WriteToLog来写日志
    但是,我 再 添加数据进库后,然后workthread读到数据后WriteToLog就写不出来了
      

  3.   

    尝试跟了一下,有点复杂。建议你在你期望写日志的地方增加printf或者afxmsgbox之类的东西,这样可以定位是写日志函数有问题还是线程逻辑跳转有问题。根据错误地方再进行分类。
      

  4.   

    tomcat_jb(老猫)
    我跟的时候是 每次能够顺利进入WriteToLog,但就是写不进内容到文本文件中去。
      

  5.   

    你的写日志函数里面看看
    file.Open(strFileName,CFile::modeWrite);
    file.SeekToEnd();
    file.WriteString(str);
    这三个操作的返回值,看到你没有判断返回值,应该根据返回值能够得到失败的原因。
      

  6.   

    我觉得和EnterCriticalSection(&g_logsec);互斥有关。
    你把互斥的部分先去掉,看还能不能写进入?