进度条直到漫长的过程

时间:2014-12-29 12:52:50

标签: c# multithreading progress-bar

我在.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。之后回来......我不明白为什么?

3 个答案:

答案 0 :(得分:1)

您正在从另一个线程中访问控件(button1button2),而不是创建它们的主线程。正如消息所说,这是无效的。

一种选择是在生成新线程之前简单地禁用按钮:

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表达式。如果你向该方法添加更多东西,以某种方式建议,以提高可读性。