user3755701
user3755701

Reputation: 21

Progress bar until long process

i have program (winform) in .NET 3.5, which send files to ftp servers. I want progress bar, i try to use thread in backround, but i have error.

This is sample of my code:

private void Odeslat_Click(object sender, EventArgs e)
{
    Thread thread = new Thread(Process);
    thread.IsBackground = true;
    thread.Start();        
}

public void Process()
{
    button1.Enabled = false;
    button2.Enabled = false;

    foreach (string Prodejna in SeznamProdejen)
    {
        i = i + 1;
        Update1(i);

        //some long task
    }
}

public void Update1(int i)
{
    if (InvokeRequired)
    {
        this.BeginInvoke(new Action<int>(Update1), new object[] { i });
        return;
    }

    progressBar1.Value = i;
 }

I have error here:

button1.Enabled = false;

This error:

{"Operation between threads is not valid: Access to the control button1 took place from another thread than the thread under which it was created."}

In public void process i have program, which send files to ftp servers.

!!!!!!But now i have problem, This is sample of my code now:!!!!

private void Odeslat_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            button2.Enabled = false;

            Thread thread = new Thread(Process);
            thread.IsBackground = true;
            thread.Start();  

            MessageBox.Show("Výsledek odesílání naleznete v souboru vysledek.txt", "Výsledek");
            button1.Enabled = true;
            button2.Enabled = true;
        }

public void Process()
        {
        foreach (string Prodejna in SeznamProdejen)
                {
            i = i + 1;
                        Update1(i);

            //some long task

                        ..............
                        Stream reqStream = request.GetRequestStream();   //PROBLEM
                                reqStream.Write(buffer, 0, buffer.Length);
                                reqStream.Close();
                        .................
        }
    }

public void Update1(int i)
        {
            if (InvokeRequired)
            {
                this.BeginInvoke(new Action<int>(Update1), new object[] { i });
                return;
            }

            progressBar1.Value = i;
        }

PROBLEM: when is program near Stream reqStream = request.GetRequestStream(); jump to private void Odeslat_Click to messagebox.show. And after that back...i dont understand why?

Upvotes: 0

Views: 701

Answers (3)

d4Rk
d4Rk

Reputation: 6683

You can access controls from background threads by invoking them.

See: Control.Invoke() http://msdn.microsoft.com/de-de/library/zyzhdc6b(v=vs.110).aspx

So in your case, just could just do:

this.Invoke(new Action(() => { 
    button1.Enabled = false; 
    button2.Enabled = false;
} ));

Of course you could also define an extra method instead of using a lambda expression. Thats somehow recommended if you add more stuff to that method, to improve readability.

Upvotes: 0

ZoomVirus
ZoomVirus

Reputation: 615

Add a timer inside your designer (timer 1 in my example) set the timer to check as often as you like. Set the time interval to one that will suit you (for 1 second checks set to 1000).

bool progress = false;
private void Odeslat_Click(object sender, EventArgs e)
{
    progress = true;
    timer1.Start();
    Thread thread = new Thread(Process);
    thread.IsBackground = true;
    thread.Start();        
}

private void timer1_Tick(object sender, EventArgs e)
{
    if(!progress)
    {
        button1.Enabled = true;
        button2.Enabled = true;
        timer1.Stop();
    }else
    {
        button1.Enabled = false;
        button2.Enabled = false;
    }
}

public void Process()
{
    foreach (string Prodejna in SeznamProdejen)
    {
        i = i + 1;
        Update1(i);

       //some long task
    }
    progress = false;
}

Upvotes: 0

Jan K&#246;hler
Jan K&#246;hler

Reputation: 6030

You're accessing controls (button1 and button2) from within another thread than the main thread on which they were created. So as the message says, this is invalid.

One option would be to simply disable your buttons before you spawn the new thread:

private void Odeslat_Click(object sender, EventArgs e)
{
    button1.Enabled = false;
    button2.Enabled = false;

    Thread thread = new Thread(Process);
    thread.IsBackground = true;
    thread.Start();        
}

Upvotes: 1

Related Questions