Reputation: 21
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
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
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
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