我在.NET 3.5中有程序(winform),它将文件发送到ftp服务器。我想进度条,我尝试在后台使用线程,但我有错误。
这是我的代码示例:
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;
}
我在这里有错误:
button1.Enabled = false;
此错误:
{"Operation between threads is not valid: Access to the control button1 took place from another thread than the thread under which it was created."}
在public void进程中,我有程序,它将文件发送到ftp服务器。
!!!!!!但现在我有问题,这是我的代码示例:!!!!
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;
}
问题:当程序接近Stream reqStream = request.GetRequestStream();跳转到私有虚空Odeslat_Click到messagebox.show。之后回来......我不明白为什么?
答案 0 :(得分:1)
您正在从另一个线程中访问控件(button1
和button2
),而不是创建它们的主线程。正如消息所说,这是无效的。
一种选择是在生成新线程之前简单地禁用按钮:
private void Odeslat_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = false;
Thread thread = new Thread(Process);
thread.IsBackground = true;
thread.Start();
}
答案 1 :(得分:0)
在设计器中添加一个计时器(在我的示例中为计时器1)将计时器设置为随意检查。将时间间隔设置为适合您的时间间隔(1秒检查设置为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;
}
答案 2 :(得分:0)
您可以通过调用它们来访问后台线程中的控件。
请参阅:Control.Invoke()
http://msdn.microsoft.com/de-de/library/zyzhdc6b(v=vs.110).aspx
所以在你的情况下,就可以这样做:
this.Invoke(new Action(() => {
button1.Enabled = false;
button2.Enabled = false;
} ));
当然,您也可以定义一个额外的方法,而不是使用lambda表达式。如果你向该方法添加更多东西,以某种方式建议,以提高可读性。