0

I have an automated mail client application, I need to show a 'Connecting...' picture during the period when the mail is retrieved.

    // *************************************
    private void Form1_Load(object sender, EventArgs z)
    {
        aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
        aTimer.Interval = 20000;
        aTimer.Enabled = true;

        CheckMail();
    }


    // *************************************
    private void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        CheckMail();
    }

    // *************************************
    void CheckMail() {

        SetPictureSwitch();

        //picEmail.visible=true

        {
           // procedure to check mail and update Grid list....
        }

        SetPictureSwitch();

        //(picEmail.visible=false)
    }

    // *************************************
    // picEmail is a simple image with wait... icon        

    private void SetPictureSwitch()
    {
        if (picEmail.InvokeRequired)
        {
            picEmail.Invoke(new MethodInvoker(
            delegate ()
            {
                picEmail.Visible = !picEmail.Visible;
            }));
        }
        else
        {
            picEmail.Visible = !picEmail.Visible;
        }

        Application.DoEvents();
    }

    // *************************************
    private void btnRefresh_Click(object sender, EventArgs e)
    {
        CheckMail();
    }

I tried any kind of thread management but without success, the pic didn't get displayed or receive a 'cross thread error'. If I use the btnRefresh only then it works fine.

What's the right way to make the pic visible when CheckMail() starts and to hide it when CheckMail() is completed?

Why it is so hard to set visible=true ? (I'm sorry I come from VB6 :))

BenKoshy
  • 33,477
  • 14
  • 111
  • 80
  • Reason: its a bad plan to use the UI thread to do hard work, so a lot of things should be off loaded to a (or more) thread(s) to do that leaving the UI responsive (eg not showing as non responsive) so the user can not get errors and warnings and unable to move the window while it does stuff - but the down side is, you cant directly update the UI from a thread that isnt its.. so.. – BugFinder Jan 10 '18 at 11:15
  • 1
    Using Application.DoEvents is discouraged; instead forward work to be done to control's thread (see https://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the) - assuming the work is done in a separate thread. – Alex Paven Jan 10 '18 at 11:17
  • Thanks for suggestions! – user3512156 Jan 10 '18 at 11:23

1 Answers1

0

I believe to have found a kind of solution not sure the best.

    // *************************************
    private void Form1_Load(object sender, EventArgs z)
    {
        aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
        aTimer.Interval = 20000;
        aTimer.Enabled = true;

        CheckMail();
    }

    // *************************************
    private void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        CheckMail();
    }

    // *************************************
    void updatePic()
    {
        if (InvokeRequired)
        { Invoke(new MethodInvoker(switchPic)); }
        else
        { switchPic(); }
    }

    // *************************************
    void switchPic()
    {
        picEmail.Visible = !picEmail.Visible;
    }

    // *************************************
    void CheckMail() {

        updatePic(); // visible=true

        {            
            // procedure to check mail and update Grid list (with another Invoke)
        }

        updatePic(); // visible=false
    }

This appear to works.