【问题标题】:Progress Bar Freezes part way进度条部分冻结
【发布时间】:2014-01-20 23:01:42
【问题描述】:

所以在下面的 sn-p 中,我非常简单地查看特定文件夹并将图像从源复制到目标。

复制速度非常快,它适用于第一批文件夹(可能是 20 个左右),这需要几秒钟。但随后进度条停止移动,我得到一个旋转的鼠标光标。我可以查看目标文件夹,它仍在处理文件夹。

完成后,我得到“进程完成”对话框,进度条为 100%,一切正常。

只是想确保最终用户不会认为它被冻结了。

private void readInvoices()
        {
            string InvoiceFile = txtInvoiceFile.Text;
            //read in the text file and get all the invoices to copy
            string[] Invoices = File.ReadAllLines(InvoiceFile);
            //set the max val of the progress bar
            progBar.Maximum = Invoices.Length;

            try
            {
                //for every invoice
                foreach (string invoice in Invoices)
                {

                    //Set the source and destination directories
                    string sourceInvFolder = string.Format(@"{0}\{1}", txtSource.Text, invoice);
                    string destInvFolder = string.Format(@"{0}\{1}", txtDest.Text, invoice);
                    DirectoryInfo SourceDI = new DirectoryInfo(sourceInvFolder);
                    DirectoryInfo DestDI = new DirectoryInfo(destInvFolder);

                    //we know we have it in the CSV but does the directory actually exist?
                    //if so then let's process
                    if (Directory.Exists(SourceDI.FullName) == true)
                    {
                        //let's copy of the files
                        CopyAll(SourceDI, DestDI);
                        RenameFolder(sourceInvFolder);
                    }
                    //inc the progress bar
                    progBar.Increment(1);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error" + ex.Message);
            }
            finally
            {
                MessageBox.Show("Process Complete");
                CleanUp();
            }


        }

【问题讨论】:

  • 我的猜测是您在 UI 线程中完成所有这些工作。那肯定会冻结事情。不过,我们目前无法确定,因为我们无法确定您是如何调用您的方法的。一般来说,不要在 UI 线程中做繁重的工作。

标签: c# progress-bar


【解决方案1】:

UI 冻结,因为它在单个线程中运行。解决冻结部分的解决方法是将这行代码放入循环中。

 Application.DoEvents();

此代码检查是否有消息等待处理,如果有,它会在继续执行另一个循环之前处理它们。您可以使用 ProgressBar 控件让用户查看已经处理了多少。如果您不想继续使用单线程方法,请使用 BackGroundWorker 以防止表单看起来像冻结一样。这是多线程,这意味着一个单独的线程正在处理某事而你做其他事。

有一点要记住,使用上面的代码会使整个循环过程变慢,因为它必须检查每个循环,这意味着更多的工作,作为回报,您可以获得实时进度报告。它看起来冻结的原因是循环尚未完成,您必须先让它完成,然后才能执行其他操作,因为它在单个线程中运行。

【讨论】:

  • 请注意,DoEvents 如果使用不当,可能会导致有趣的(对我来说很有趣,而不是你)副作用。例如,在循环仍在运行时关闭表单不会停止您的程序。无论如何,直到程序退出循环。您可以尝试查找并防止所​​有这些极端情况,但您将花费与学习正确方法的异步编程一样多的时间。
  • @Steven Liekens,我完全同意。 DoEvents 并不是所有事情的最佳解决方案。但它确实适用于更简单的问题。当涉及大量工作时,多线程是要走的路:)
  • 因为这个过程是如此之快......我不介意用.DoEvents来完成它。谢谢!
  • @Matt Winer,就是这样 :) 这个过程太快了,等待时间根本不会打扰我。这就是为什么我大部分时间都使用 DoEvents,即使我也做过多线程 :)
【解决方案2】:

如果你想要Just want to make sure the end user doesn't think it's frozen.,你应该使用多线程。更适合这个任务的类是BackgroundWorker

来自 MSDN:

BackgroundWorker 类允许您在单独的专用线程上运行操作。下载和数据库事务等耗时的操作可能会导致您的用户界面 (UI) 在运行时似乎停止响应。当您需要响应式 UI 并且面临与此类操作相关的长时间延迟时,BackgroundWorker 类提供了一种方便的解决方案。

尝试按照 msdn 提供的示例,将您的方法的调用 readInvoices() 放入 DoWork 事件中

【讨论】:

    【解决方案3】:

    您的代码在 UI 线程上运行(至少我假设您的 catch 块中有一个 MessageBox)。

    因此,它不一定会处理 UI 更新。

    看看使用 TPL 完成这项工作。

    http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多