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

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

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

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

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

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

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

此致,Swanand

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

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

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

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

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

您正在阻止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(); } } 

您正在阻止主UI线程。 您可以使用后台工作程序来执行此操作。 您可以在MSDN中找到更多详细信息

Marc建议的答案会有所帮助。 Lon运行操作可能会使您的应用程序崩溃或无法响应。 我有一篇与后台工作者类的用法相关的博客文章。

http://midnightprogrammer.net/post/Using-Background-Worker-in-C.aspx

如果要运行代码,则应将此代码放在函数中,并使用一个线程调用此函数。

  public static void fun1() { for (int i = 0; i <= 10; i++) { Console.Write("This is function1"); Console.Write("\n"); } } Thread firstthread = new Thread(new ThreadStart(fun1)); firstthread.Start(); firstthread.suspend();//whenever you want your current control to stop. 

b'caz Thread.sleep(100)将停止整个上下文而不是你想要的那个...