【问题标题】:creating a log file using windows api C++ [closed]使用 Windows api C++ 创建日志文件 [关闭]
【发布时间】:2012-04-02 08:50:31
【问题描述】:

我已经编写了一个代码来使用 CreateFile API 在文本文件中写入一些值 但是当我执行代码时,有时记录的值是正确的,但是 有时它们只是奇怪的符号。我不知道是什么问题。请告诉我我的代码有什么问题。 提前谢谢

#pragma  once
#define  max_threads 5
#define  buf_size 255
#include "7febdll_varnum.h"
#include <fstream>
#include <iostream>
#include <string>
#include <windows.h>
#include <iomanip>  
#include <assert.h>
#include <sstream>
#include <tchar.h>
const wchar_t* MUTEXNAME = L"Example Mutex";
    }

我正在提供类似的输入

void main()
{
    varunthread::fvarunthread::myfn("varun /n%d%d mehta /n deepanshu goyal /n",1,2);
    varunthread::fvarunthread::myfn("varunmehta2/n");
    varunthread::fvarunthread::myfn("varunmehta3");
}

【问题讨论】:

  • .但我会开始..不要为每个日志写入创建一个新线程。一旦围绕生产者-消费者队列循环,只需创建一个线程。如果队列需要互斥体来保护它,等待互斥体的正确方法是使用等待 API,例如“WaitForSingleObject()”。如果您想要一些巧妙的格式化内容,请将其封装在“logData”类中并将类实例排队到写入线程。
  • 如果您需要了解多线程和线程间通信,最好不要急于交付。经过一些经验,编写可靠有效的线程内容并不难,但您必须首先通过“灾难性错误”阶段。
  • @hardyz009 - Google for 'WaitForSingleObject'
  • @hardyz009 - 我必须给你满分才能真正实现一些东西并让它完全发挥作用。如果您使用 Windows 等待函数(例如 WaitForSingleObject())来等待互斥体,您的代码可能会低效但正确地工作。您不需要在每个线程中打开互斥锁 - 只需传入互斥锁句柄并等待它。如果只有一个进程写入文件,则互斥体不需要名称,(事实上,可以用更快的“关键部分”替换)。
  • @hardyz009 两个字:写英文你不能把“和”写完整,校对你的cmets吗?你不是在乞求 5 岁孩子的写作风格的帮助

标签: windows file winapi visual-c++


【解决方案1】:

导入一个已经可以正常工作的日志类。

如果做不到这一点,请开始使用 Windows 等待函数在互斥体上等待来修复您的代码。如果你用谷歌搜索'WaitForSingleObject',你应该能够很容易地使用它——你需要将互斥体句柄传递给每个线程,以便他们可以等待它。您显然可以编写足够好的代码,您只需要更多线程、信号和线程间通信方面的经验。

哦 - 看看 'lpLogString' 的生命周期 - 它在哪里处理?我没有使用过 TCHAR,但是,AFAIK,所有新的东西都应该被处理掉。我猜它应该在写入文件后在写入线程中处理。

你真的需要重构你的整个设计,只使用一个在队列中等待东西的线程。为每次写入创建新线程效率极低,并且可能导致写入顺序有点不确定,因为线程获取互斥锁的顺序不能保证是 FIFO。

您将“lpLogString”作为 CreateThread() 参数传递给每个线程(正确!),但不会在写入线程中检索它!你必须在每个写入线程中使用'LPVOID lpParam'来检索字符串数据,否则会有很大的问题。

..这最终导致了这样的想法'所有这些数据仅通过一个指针传递给线程,我不妨声明一个可以包含格式字符串、互斥句柄和其他任何东西的类。然后我可以创建一个,加载它并将其指针传递给线程。它可以包含所有这些特殊的格式化命令和代码作为方法——然后写入线程可以进行所有格式化,这样我的主应用程序就不必这样做了。线程可以在稍后处理完 'thread comms' 实例后对其进行 dispose()。

..这最终导致了一个想法'现在我有了这个'线程通信'类,我可以将它的实例排队到生产者-消费者队列上的一个线程,而不是不断地创建新线程。我可以将生产者-消费者队列的实例传递给 LPVOID lpParam 事物中的线程。

//在标题中:

   class ThreadComms {
    private:
    public:
      int dataLen;
      TCHAR *lpLogString;
      HANDLE hMutex;
      ThreadComms(String data);
      ~ThreadComms();
    };

//在cpp中

ThreadComms::ThreadComms(String data){
    dataLen=data.Length();
    lpLogString=new TCHAR[dataLen+1];
    strcpy(( char *)lpLogString,(char *)data.c_str());
};

ThreadComms::~ThreadComms(){
  delete(lpLogString);
};

    HANDLE hthread;
    DWORD dwthreadid;
    DWORD _stdcall MyThreadFunction(LPVOID lpParam)
    {
        ThreadComms *inThreadComms=(ThreadComms *)lpParam;

        DWORD dwNumBytesWritten = 0;
        HANDLE hFile;
        WaitForSingleObject(inThreadComms->hMutex,INFINITE);
        hFile = CreateFile(FILENAME,
                            FILE_APPEND_DATA,
                            FILE_SHARE_WRITE,
                            NULL,
                            OPEN_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);

         WriteFile(hFile,
                    (char *)inThreadComms->lpLogString,
                    inThreadComms->dataLen,
                    (LPDWORD)&dwNumBytesWritten,
                    NULL );

        CloseHandle( hFile );
        ReleaseMutex(inThreadComms->hMutex);
        delete(inThreadComms);
    }

    void myfn(const String inMess)
    {
        HANDLE hMutex;
        hMutex=CreateMutex(NULL,FALSE,"");
        assert(hMutex!=NULL);
        ThreadComms *threadComms=new(ThreadComms)(inMess);

        CreateThread(NULL,
                                0,
                                MyThreadFunction,
                                threadComms,
                                0,
                                &dwthreadid);
        CloseHandle(hthread);
    }

..或者,更好的例子,(至少,它在 C++ Builder 中):

//在标题中:

    class PCqueue{
    private:
        CRITICAL_SECTION access;
        deque<void*> *objectQueue;
        HANDLE queueSema;
    public:
        PCqueue();
        void push(void *ref);
        bool pop(void**ref,DWORD timeout);
    };

   class ThreadComms {
    private:
    public:
      int dataLen;
      TCHAR *lpLogString;
      ThreadComms(String data);
      ~ThreadComms();
    };

  class ThreadLogger {
    private:
        PCqueue *queue;
        HANDLE logThread;
        HANDLE fileAccess;
        AnsiString Ffilename;
        static DWORD _stdcall staticThreadRun(void *param){
            ((ThreadLogger*)param)->threadRun(0);
        };
    public:
        void threadRun(void *param);
        ThreadLogger(String filename);
        void logString(String data);
  };

//在cpp中:

PCqueue::PCqueue(){
    objectQueue=new deque<void*>;
    InitializeCriticalSection(&access);
    queueSema=CreateSemaphore(NULL,0,MAXINT,NULL);
};

void PCqueue::push(void *ref){
    EnterCriticalSection(&access);
    objectQueue->push_front(ref);
    LeaveCriticalSection(&access);
    ReleaseSemaphore(queueSema,1,NULL);
};

bool PCqueue::pop(void **ref,DWORD timeout){
    if (WAIT_OBJECT_0==WaitForSingleObject(queueSema,timeout)) {
        EnterCriticalSection(&access);
        *ref=objectQueue->back();
        objectQueue->pop_back();
        LeaveCriticalSection(&access);
        return(true);
    }
    else
        return(false);
};




ThreadComms::ThreadComms(String data){
    dataLen=data.Length();
    lpLogString=new TCHAR[dataLen+1];
    int index=0;
    for(index=0;index<dataLen;index++){lpLogString[index]=data[index+1];};
};

ThreadComms::~ThreadComms(){
  delete(lpLogString);
};


ThreadLogger::ThreadLogger(String filename){
    Ffilename=filename;
    fileAccess=CreateMutex(NULL,FALSE,"Example Mutex");
    queue=new PCqueue();
    logThread=CreateThread(NULL,
                0,
                staticThreadRun,
                this,
                0,
                0);
};

void ThreadLogger::threadRun(void *param){
    ThreadComms *inMess;
    DWORD dummy;
    while(queue->pop((void**)&inMess, INFINITE)){
        HANDLE hFile;
        WaitForSingleObject(fileAccess,INFINITE);
        hFile = CreateFile( &Ffilename[1],
                            FILE_APPEND_DATA,
                            FILE_SHARE_WRITE,
                            NULL,
                            OPEN_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);
         WriteFile(hFile,
                    (char *)inMess->lpLogString,
                    inMess->dataLen,
                    &dummy,
                    NULL );

        CloseHandle( hFile );
        ReleaseMutex(fileAccess);
        delete(inMess);
    };
};


void ThreadLogger::logString(String data){
    ThreadComms *threadComms=new(ThreadComms)(data);
    queue->push(threadComms);
};

【讨论】:

  • 马丁你能把我做不到的整个代码贴出来好吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多