oprettelse af en logfil ved hjælp af windows api C ++

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har skrevet en kode til at skrive nogle værdier i en tekstfil ved hjælp af CreateFile API
        Men når jeg udfører koden nogle gange, er de loggede værdier korrekte, men
 nogle gange er de bare svære symboler. Jeg kan ikke finde ud af, hvad der er problemet. Fortæl mig hvad der er galt i min kode.
                  tak på forhånd


#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";
    }


Jeg giver input gerne


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");
}

Bedste reference


Importer en log klasse, der allerede fungerer OK.


Hvis du undlader det, begynder du at rette din kode ved at bruge en Windows Vent-funktion til at vente på mutex. Hvis du Google for 'WaitForSingleObject', skal du kunne bruge det nemt nok - du skal passere mutex håndtaget i hver tråd, så de kan vente på det. Du kan selvfølgelig skrive kode nok nok, du har bare brug for mere erfaring med gevindskæring, signalering og inter-thread comms.


Åh - se på livet af 'lpLogString' - hvor er den bortskaffet? Jeg har ikke brugt TCHAR, men AFAIK, alt, hvad der er nyt, skal bortskaffes. Jeg gætter på, at det skal afsættes i skrive-tråden efter at have skrevet det til filen.


Du har alvorligt brug for at refactor hele dit design til at bruge kun en tråd, der venter på en kø for ting. Oprettelse af nye tråde for hver skrivning er grovt ineffektiv og vil sandsynligvis føre til en noget ubestemt skriveordre, da ordren, hvor tråde får mutexen, ikke garanteres at være FIFO.


Du sender 'lpLogString' til hver tråd som en CreateThread () parameter, (korrekt!), Men ikke genoptræder den i skrivetråden! Du skal hente strengdataene i hver skrive tråd ved hjælp af 'LPVOID lpParam', ellers vil der være store problemer.


.. som i sidste ende fører til tanken 'med al denne dataoverførsel til tråde via kun en pointer, kan jeg lige så godt erklære en klasse, der kan indeholde formatstrengen, mutexhåndtaget og alt andet, der kommer op. Opret en, lad den op og send dens peger til tråden. Den kunne indeholde alle de specielle formateringskommandoer og kode som metoder - skrivetråden kunne så gøre alt, hvad der formateres, så min hovedapplikation ikke behøver at. Tråden kan bortskaffe () af 'thread comms' -eksemplet senere, når det er færdigt med det.


.. som i sidste ende fører til tanken 'Nu har jeg denne' thread comms '-klasse, jeg kunne køe forekomster af den til en tråd på en producent-forbruger kø i stedet for konstant at skabe nye tråde. Jeg kunne passere forekomsten af producent-forbruger kø til tråden i den LPVOID lpParam ting '.


//i overskriften:


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


//i 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);
    }


.. eller et bedre eksempel, der fungerer (i det mindste gør det i C ++ Builder):


//i overskriften:


    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);
  };


//i 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);
};