在C#中执行任何其他操作时表单无响应

Swa*_*and 10 c# winforms

我有一个表单(使用VS2010在C#中开发)和一个进度条.这是一种秒表形式,我填写进度条说10secs ....随着时间流逝,进度条相应填充....意味着5secs后,进度条将填充50%等等....

我使用for循环来执行此操作: -

for(int count=0;count<200;count++)
{
   progbar.performstep();
   progbar.update();
   update();
   Thread.Sleep(50);
}
Run Code Online (Sandbox Code Playgroud)

我使用了50毫秒的Thread.Sleep,以便进度条顺利更新.持续1秒,它会逐步递增.

问题是,如果我做任何其他操作,如移动此表单,甚至点击桌面上的另一个图标使这个表单"无响应"....但它执行操作,并在10秒结束时,它重新获得它的状态并显示弹出,表示进度条已满10秒.

感谢您的帮助和抱歉使用这种复杂的语言.

此致,Swanand

更新:我在下面的答案的帮助下解决了这个问题....我要知道的一个常见错误就是忘记了" Applications.DoEvents()"以及" update()"......如果你进入这一行,那么"被绞死"的机会就会减少!

Jon*_*eet 16

您正在UI线程上执行长时间运行的操作,这意味着UI"消息循环"(负责处理用户输入和更新屏幕等事件)无法运行.

您应该在不同的线程上执行长时间运行的操作(无论是您自己创建的还是后台线程),并且可以使用它BackgroundWorker来轻松更新进度条,或者Control.Invoke/BeginInvoke在需要更新时用于将委托调用回调到UI线程用户界面.(您不能从错误的线程更新控件.)

如果您的唯一UI交互正在填写进度条,我建议使用BackgroundWorker.

如果你没有真正做"真正的"工作,只是等待时间过去,你可以用一个System.Windows.Forms.Timer而不是所有这些.这将在UI线程上"勾选",但不会阻止滴答之间的UI线程.如果你没有很多工作要做,你应该只使用它 - 如果它真的只是更新进度条,而不是(比如说)处理文件等.注意你不应该完全依赖定时器"准时" - 您应该根据观察到的时间而不是观察到的刻度数来设置进度条的位置.


Mar*_*ell 10

您正在阻止UI线程,这意味着它不处理诸如"paint"之类的事件.要正确地执行此操作,您应该使用类似的东西BackgroundWorker,并且只是从progress事件更新UI.

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Threading;

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MyForm());
    }
}

class MyForm : Form
{
    Button btn;
    BackgroundWorker worker;
    ProgressBar bar;
    public MyForm()
    {
        Controls.Add(btn = new Button { Text = "Click me" });
        btn.Click += new EventHandler(btn_Click);

        Controls.Add(bar = new ProgressBar { Dock = DockStyle.Bottom, Visible = false, Minimum = 0, Maximum = 100 });

        worker = new BackgroundWorker { WorkerReportsProgress = true };
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        bar.Visible = false;
        if (e.Error != null)
        {
            Text = e.Error.Message;
        }
        else if (e.Cancelled)
        {
            Text = "cancelled";
        }
        else
        {
            Text = e.Result == null ? "complete" : e.Result.ToString();
        }
        btn.Enabled = true;
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int count = 0; count < 100; count++)
        {
            worker.ReportProgress(count);
            Thread.Sleep(50);
        }
    }

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        bar.Value = e.ProgressPercentage;
    }

    void btn_Click(object sender, EventArgs e)
    {
        bar.Value = 0;
        bar.Visible = true;
        btn.Enabled = false;
        worker.RunWorkerAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)