Thread: Need help developing an application

  1. #1
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46

    Post Need help developing an application

    Hi all!
    Here is the overview of the application I am trying to develop:
    Platform: Windows XP, Visual C++ 6
    Application type: MFC
    Features: Read a file sector by sector ( 2048 bytes) and display it in a tree view.

    Here are the problems I am facing:
    1. If I try to read a file which size is bigger than 1 GB, the program uses 100% of the CPU memory and then crashes

    2. When the program is reading a file, I want to display a Progress Bar in a new dialog. Using CDialog->DoModal, the dialog does pop up, but the progress bar doesnt work.

    Possible problem: When reading a file, I use a loop. Maybe the program stays in that loop too long leading it to crash.
    Any ideas, how I should make this work.
    First I want to keep the loop for reading a file, makes the program exit the loop anytimes a window message comes, and then resume the loop.
    Thanks in advance!
    Afrinux

  2. #2
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    I originally posted this thread in the C++ section. I was told that there is a windows section, and I have moved it here. Thanks for understanding
    Quote Originally Posted by Sebastiani
    >> Read a file sector by sector ( 2048 bytes) and display it in a tree view.

    display *what* in the treeview - the entire file, statistics, analytic information?
    actually it is an mpeg file. I display the mpeg headers informations for every sector.

    Quote Originally Posted by Sebastiani
    >> If I try to read a file which size is bigger than 1 GB, the program uses 100% of the CPU memory and then crashes

    chances are you won't be able to request that much memory using standard calls (new, malloc) - Windows has a function VirtualAlloc that may be helpful to you.
    I am not using memory allocation. I use a buffer ( unsigned char buffer[2048] )
    Code:
    while( 1 ){
       fread( buffer, sizeof(unsigned char), 2048, fp );
       // here I take out the headers informations and display them in the tree view.
    
      offset += 2048;
      if( offset >= file_size )  break;
    }
    Quote Originally Posted by Sebastiani
    >> When the program is reading a file, I want to display a Progress Bar in a new dialog. Using CDialog->DoModal, the dialog does pop up, but the progress bar doesnt work.

    try getting it to work on it's own first before incorporating it into your program - makes debugging that much easier.
    Thank you for your suggestion. Independently, the ProgressBar does work.

    Quote Originally Posted by Sebastiani
    >> Maybe the program stays in that loop too long leading it to crash.

    why would you think that a loop could crash a program (by itself)? a better guess might be stack overflow due to recursive or large stack-framed functions being used inside the loop.
    I will look into it.

    Quote Originally Posted by Sebastiani
    by the way, we have a Windows forum here that would probably be a better place for this thread.
    Thank you very much. I thought the C++ section were the appropriate section.
    Afrinux

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> I am not using memory allocation. I use a buffer ( unsigned char buffer[2048] )

    Windows set's a limit on the amount of memory available to a control. from what I remember there is a way to resize the controls internal buffer and/or have it use your own. you might look into SetWindowLong to start with:

    Reserve extra window memory by specifying a nonzero value in the cbWndExtra member of the WNDCLASS structure used with the RegisterClass function.
    >> actually it is an mpeg file. I display the mpeg headers informations for every sector.

    perhaps you could dynamically load the part of the file being displayed and unload it when that particular sector isn't being viewed in the control?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    2. When the program is reading a file, I want to display a Progress Bar in a new dialog. Using CDialog->DoModal, the dialog does pop up, but the progress bar doesnt work.
    How are you communicating the progress information to the progress dialog? Are you reading the file read through another thread?

    Possible problem: When reading a file, I use a loop. Maybe the program stays in that loop too long leading it to crash.
    Windows XP will white out the window if you stay in the loop too long without updating the GUI

    First I want to keep the loop for reading a file, makes the program exit the loop anytimes a window message comes, and then resume the loop.
    You could read from your file for 300ms or so, then return from the function. Wait 50ms or so, during which you handle other events. (You have to use the SetTimer method. The times won't be exact) Then resume, after the 200ms, the file read. Another way might be to use a worker thread.

  5. #5
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Quote Originally Posted by Sebastiani
    >> I am not using memory allocation. I use a buffer ( unsigned char buffer[2048] )

    Windows set's a limit on the amount of memory available to a control. from what I remember there is a way to resize the controls internal buffer and/or have it use your own. you might look into SetWindowLong to start with:
    I have read somewhere, if an application is in a loop the memory usage is near to 100%. I used the Sleep() function in the loop to reduce the memory usage to 4%, but the application takes more time to execute one operation.
    I will look into SetWindowLong.
    >> actually it is an mpeg file. I display the mpeg headers informations for every sector.

    perhaps you could dynamically load the part of the file being displayed and unload it when that particular sector isn't being viewed in the control?
    Sorry for my ignorance, but what is dynamically loading a file? How to dynamically load a section of a file?

    Quote Originally Posted by okinrus
    How are you communicating the progress information to the progress dialog? Are you reading the file read through another thread?
    Windows XP will white out the window if you stay in the loop too long without updating the GUI
    Threads never came in my mind. I made a single thread application.
    I think the whole problem might be laying there.
    I have never made a multithreaded windows application. I will search the net, for some tutorials regarding Threads. If someone happens to know a good site on Threads please let me know.
    You could read from your file for 300ms or so, then return from the function. Wait 50ms or so, during which you handle other events. (You have to use the SetTimer method. The times won't be exact) Then resume, after the 200ms, the file read. Another way might be to use a worker thread.
    Since it is a single threaded application, using a Timer seems to be a good idea.
    Will a Timer be necessary if I switch my application to a multithreaded application?

    Thanks again, Sebastiani, okinrus , for your time.
    Afrinux

  6. #6
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    Threads never came in my mind. I made a single thread application.
    I think the whole problem might be laying there.
    Threads will make things more complicated. I thought maybe your interthread messages might be getting lost because of your modal message box.

    I have never made a multithreaded windows application. I will search the net, for some tutorials regarding Threads. If someone happens to know a good site on Threads please let me know.
    For MFC specific stuff, this page is pretty good. I'm sort of reading up on this stuff myself.
    http://www.flounder.com/mvp_tips.htm#hreads and Processes series

    Since it is a single threaded application, using a Timer seems to be a good idea.
    Will a Timer be necessary if I switch my application to a multithreaded application?
    For the multithreaded approach, you'd want to update the progress bar at certain intervals and so using GetTickCount after every sector read will tell you when. You could probably get by without using SetTime. For the singlethreaded approach, you'd want to break things up, I think. Wen your program is reading the file, your application is blocked from processing the paint update messages. This article from the link I posted goes in more indepth on worker threads. http://www.flounder.com/workerthreads.htm

  7. #7
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Look at ReadFileEx() as it allows you to specify a callback function to handle the return from a file read. In this function you could update the progress bar, handle errors or check for msgs.

    ReadFileEx() creates a thread to read the file, doing quite a lot of the work for you.


    >>I thought maybe your interthread messages might be getting lost because of your modal message box.

    You need a modeless dialog. Modal will not allow you to send updates of the progress bar position. This is because modal dlgs do not return control (communicate with app) to the app until the dlg has been dismissed (OKed or CANCELed).

    Create a class derived from CDialog based on you progress bar dlg.
    Declare a member in you main window class of this class.
    When you need the progress bar check the dlg member variable for a 'safe' HWND. If no safe HWND create the dlg, if a safe hwnd ShowWindow().

    >>For the multithreaded approach, you'd want to update the progress bar at certain intervals

    Create a worker thread to process the file.
    When you load the file, find the file size / read buffer size. Set the progress range to this value.
    Each loop send an update to the progress bar.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  8. #8
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    You need a modeless dialog. Modal will not allow you to send updates of the progress bar position. This is because modal dlgs do not return control (communicate with app) to the app until the dlg has been dismissed (OKed or CANCELed).
    From what I understand, the modal dialog operates on its own message loop. But by using a PostMessage to the modal dialog and the progress info may be propagated. Maybe you could clarify? According to the msdn documentation, another way is to use hooks. Never tried, though.

    Look at ReadFileEx() as it allows you to specify a callback function to handle the return from a file read. In this function you could update the progress bar, handle errors or check for msgs.

    ReadFileEx() creates a thread to read the file, doing quite a lot of the work for you.
    That should work, too. He could call this function multiple times and update the progress information back to the GUI.

  9. #9
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    >>But by using a PostMessage to the modal dialog and the progress info may be propagated.

    To send the modal dlg msgs you need control/processing in your app, which you won't have until the modal dlg is cancelled/OKed.

    A modeless dlg is much easier than hooks / threads.

    //call modal dlg
    CProgDlg ProgDlg;

    ProgDlg.DoModal();
    //app/thread stops here until ProgDlg is closed.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  10. #10
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    To send the modal dlg msgs you need control/processing in your app, which you won't have until the modal dlg is cancelled/OKed.
    The view and the dialog must still be processing some types of messages during DoModal. Overlapped areas won't get drawn othewise. I'll have to try and see what happens sometime.

  11. #11
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Thanks okinrus, novacain!

    I was learning threads. I have managed to create a worker thread that read the file.
    Because of the nature of threads( still fuzzy in my head ), I left the idea of popping up a dialog, instead put the ProgressBar in the main Dialog.
    Things are working fine, but I still want to pop up a Dialog to show the progress on it.
    Second problem is, because I have to use Sleep() in the file read loop, reading a 1 GB file takes more than 20 minutes.
    Third problem is, whenever I put delete MyThread, my application always crashes. Any idea?
    I tried also:
    Code:
    GetExitCodeThread( pStreamReadTask->m_hThread, &exit_code);
    if( exit_code == STILL_ACTIVE) ){
        TerminateThread(pStreamReadTask->m_hThread,0);
    }
    but exit_code is always active. Now I have an application with a task I can't kill.

    I will look at ReadFileEx() and see if I can use it.
    Thanks again both of you for your precious time.
    P.S. okinrus, that's a good link you gave me there.

  12. #12
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Derive a class from your ProgressBar dialog (Class Wiz in MSVC v6)

    ie CProgressBarDlg

    In the header for the Progresbar's parent's class (the window that will call the Progressbar)

    //add the ProgressBar dialogs header
    #include "CProgressBarDlg.h"

    //add a member variable
    CProgressBarDlg m_ProgressBarDlg;

    When you need to show the progressbar dialog

    //This calls the progressbar dialog
    Code:
    //check to see if the Progressbar Dlg has already been created
    if(m_ProgressBarDlg.GetSafeHwnd())
    	m_ProgressBarDlg.ShowWindow(SW_SHOW);
    else
    	m_ProgressBarDlg.Create(IDD_PROGRESSBAR_DLG,this);
    //make sure visible
    m_ProgressBarDlg.ShowWindow(SW_SHOW);
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  13. #13
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Quote Originally Posted by novacain
    Derive a class from your ProgressBar dialog (Class Wiz in MSVC v6)

    ie CProgressBarDlg

    In the header for the Progresbar's parent's class (the window that will call the Progressbar)

    //add the ProgressBar dialogs header
    #include "CProgressBarDlg.h"

    //add a member variable
    CProgressBarDlg m_ProgressBarDlg;

    When you need to show the progressbar dialog

    //This calls the progressbar dialog
    Code:
    //check to see if the Progressbar Dlg has already been created
    if(m_ProgressBarDlg.GetSafeHwnd())
    	m_ProgressBarDlg.ShowWindow(SW_SHOW);
    else
    	m_ProgressBarDlg.Create(IDD_PROGRESSBAR_DLG,this);
    //make sure visible
    m_ProgressBarDlg.ShowWindow(SW_SHOW);
    Hi novacain. Thanks for the reply.
    I am having a compile error here m_ProgressBarDlg.Create(IDD_PROGRESSBAR_DLG,this);
    After checking the function Create, it needs 4 parameters instead of 2 as follow: ::Create( DWORD, RECT, CWnd, ID )

  14. #14
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    Second problem is, because I have to use Sleep() in the file read loop, reading a 1 GB file takes more than 20 minutes.
    I don't think sleep is needed.


    Third problem is, whenever I put delete MyThread, my application always crashes. Any idea?
    You need to set m_bAutoDelete to false and make sure the thread isn't running. I do
    Code:
        CWinThread* thread = AfxBeginThread(run, 0, THREAD_PRIORITY_NORMAL,
            0, CREATE_SUSPENDED);
    
        thread->m_bAutoDelete = false;
    
        thread->ResumeThread();
    The reason I first create the thread suspended is that the thread could conceivably complete before m_bAutoDelete is asigned. This way the thread is suspended when the m_bAutoDelete is assigned. The Website link I gave to you before goes into more depth. When I make sure to wait for the thread to exit. I do
    Code:
        WaitForSingleObject(readWorkerThread_->m_hThread, INFINITE);
        delete readWorkerThread_;
        readWorkerThread_ = 0;
    I know when this code is run the thread is about to exit because this code is executed when the view receives UWM_FINISHED_READ(which is posted to the view when the thread is about to exit). Before this code is executed, the static stop variable is set inside the thread so that the thread proc will eventually exit.

    The thread callback itself might look something like
    Code:
    UINT ReadWorker::run(LPVOID paramPtr)
    {
        int lineno = 0;
        
        ReadWorker::waitForInitializeProgressDialog();
    
        std::ifstream in(filename_.c_str());
    
        while(!stop_ && !in.eof())
        {
            std::string line;
            std::getline(in, line);
    
            lineno++;
    
            if (in)
            {
                  ProgressInfo* info = new ProgressInfo(lineno, line);
    
                  WPARAM wp = reinterpret_cast<WPARAM>(info);
                  PostMessage(view_, UWM_PROGRESS_UPDATE, wp, 0);
                  Sleep(1000);
             }
        }
    
        bool isCancelation = stop_;
        ReadFinishInfo* finfo = new ReadFinishInfo(isCancelation);    
        
        WPARAM wpInfo = reinterpret_cast<WPARAM>(finfo);
    
        PostMessage(view_, UWM_FINISHED_READ, wpInfo, 0);
        
        return 0;
    }
    The stop_ variable is declared volatile because it is changed and read from two different threads. The windows that receive the messages are responsible for deleting their parameters.

  15. #15
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Hi onkirus! Thanks for your tips. Now the thread can be deleted without the application crashing.
    Here is the code:
    Starting the Thread:
    Code:
    	pStreamReadTask = new CDVDStreamReadTask();
    	pStreamReadTask->CreateThread( CREATE_SUSPENDED, 0 );
    	pStreamReadTask->m_bAutoDelete = FALSE;
    	pStreamReadTask->ResumeThread();
    Killing the Thread:
    Code:
    	WaitForSingleObject( pStreamReadTask->m_hThread, 1000 );
    	delete pStreamReadTask;
    	pStreamReadTask = NULL;
    There is one problem, I have here. If I replace 1000 by INFINITE in WaitForSingleObject() like this --> WaitForSingleObject( pStreamReadTask->m_hThread, INFINITE ); the application stops there.
    Any idea what might cause the problem.

    I don't think sleep is needed.
    When I take out sleep(), the cpu usage reaches 100% and can't cancel the process.

    Thanks for your time.
    Afrinux

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help for developing an application
    By Afrinux in forum C++ Programming
    Replies: 4
    Last Post: 03-03-2006, 02:03 AM
  2. Problem with com application
    By amardon in forum C++ Programming
    Replies: 3
    Last Post: 10-06-2005, 05:50 AM
  3. MFC run application by clicking on file...
    By dug in forum Windows Programming
    Replies: 4
    Last Post: 12-02-2004, 04:33 AM
  4. Developing TCP/IP Application in Microsoft Visual Studio VC++
    By ashu12 in forum Windows Programming
    Replies: 1
    Last Post: 09-11-2002, 03:30 AM