【问题标题】:Progressbar not progressing进度条没有进展
【发布时间】:2012-02-19 15:14:25
【问题描述】:

我是 C# 新手,想问一个问题。

我正在开发一个 Windows 应用程序并尝试插入一个进度条,当我从另一个命名空间调用它时它不起作用。

我的代码:

namespace CLT
{
    public partial class GenBulkReceipts : UserControl
    {
        public void ProressBarMovement()
        {
            progressBar1.PerformStep();
        }

        public void LoadProgressBar(int progressbarMax)
        {
            progressBar1.Minimum = 1;
            progressBar1.Maximum = progressbarMax;
            progressBar1.Value = 1;
            progressBar1.Step = 1;
        }

private void btnOpen_Click(object sender, EventArgs e)
{
   try
   {
     OpenFile();
    }
}

private void OpenFile()
{
       if (dsEx1.Tables[0].Rows.Count > 0)
      {
        AccountsToBeImported = new BLLService().Get_AccountsToBeReceipted(dsEx1);
      } 
}
}

namespace BLL
{
    class GenBulkReceiptsBLL
    {
        public DataSet Get_AccountsToBeReceipted(DataSet dsImport)
        {
                  CLT.GenBulkReceipts pb = new CLT.GenBulkReceipts();
                  pb.LoadProgressBar(dsImport.Tables[0].Rows.Count); 

                  foreach (DataRow dr in dsImport.Tables[0].Rows)
            {
                          //Code cgoes here 
                  }
                  pb.ProressBarMovement();
               }
      }
  }

如果有任何帮助,我将不胜感激

谢谢你

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    它不动的原因是(我假设)您在同一个线程上完成所有工作。您可能希望在单独的线程上执行此处理,例如使用 BackGroundWorker

    【讨论】:

    • 我认为这可能是 OP 没有看到进度条更新的原因。
    • 除了在 foreach 循环之外增加值
    【解决方案2】:

    这里有几件事。首先,将ProressBarMovement() 代码移动到您的循环中:

    foreach (DataRow dr in dsImport.Tables[0].Rows) {
        //Code cgoes here 
        pb.ProressBarMovement();
    }
    

    您可能还必须强制重新绘制进度条。这就是Refresh() 正在做的事情:

    public void ProressBarMovement() {
        progressBar1.PerformStep();
        progressBar1.Refresh();
    }
    

    【讨论】:

    • 真的很抱歉上面的代码示例有点不对 pb.ProressBarMovement();在foreach循环中
    • 如果您已经在foreach 循环中调用了ProressBarMovement(),那么问题是每次迭代都没有处理UI 更新。乔尔在他的回答中也提到了这一点。要么将数据处理转移到另一个线程,要么强制 UI 元素在每次迭代时更新。
    【解决方案3】:

    这里的关键是线程。我在当天做一些 WPF 的事情时遇到了同样的问题。我最终使用后台任务来更新我的 UI,并且一旦我添加了一切工作顺利。

    看看这个帖子,这和你遇到的问题一样。 How to update GUI with backgroundworker?

    这里还有 microsoft 链接,以便您了解后台工作人员的实际操作。 http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

    希望这会有所帮助。

    编辑:提供代码以帮助实现目标。

    namespace CLT
    {
        public partial class GenBulkReceipts : UserControl
        {
            public void ProressBarMovement()
            {
                progressBar1.PerformStep();
            }
    
            public void LoadProgressBar(int progressbarMax)
            {
                progressBar1.Minimum = 1;
                progressBar1.Maximum = progressbarMax;
                progressBar1.Value = 1;
                progressBar1.Step = 1;
            }
    
            private void btnOpen_Click(object sender, EventArgs e)
            {
                try
               {
                   OpenFile();
                }
            }
    
            private void OpenFile()
            {
                if (dsEx1.Tables[0].Rows.Count > 0)
                {
                    AccountsToBeImported = new BLLService().Get_AccountsToBeReceipted(dsEx1);
                } 
            }
    }
    
    namespace BLL
    {
        class GenBulkReceiptsBLL
        {
            DataSet _dsImport;
            BackgroundWorker _backgroundWorker;
            CLT.GenBulkReceipts _pb;
    
            public GenBulkReceiptsBLL()
            {
                _backgroundWorker = new BackgroundWorker();
                _backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
                _backgroundWorker.OnProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
                _backgroundWorker.ReportsProgress = true;
            }
    
            public DataSet Get_AccountsToBeReceipted(DataSet dsImport)
            {   
                _pb = new CLT.GenBulkReceipts();
                _pb.LoadProgressBar(dsImport.Tables[0].Rows.Count);
                _dsImport = dsImport;
    
                _backgroundWorker.RunWorkerAsync();  
            }
    
            public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
            {           
                int p = 0;  // set your progress if appropriate
                object param = "something"; // use this to pass any additional parameter back to the UI
    
                foreach (DataRow dr in _dsImport.Tables[0].Rows)
                {
                    _backgroundWorker.ReportProgress(p, param);
                } 
            }
    
            // This event handler updates the UI
            private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                _pb.ProressBarMovement();
            }
        }
    }
    

    【讨论】:

    • 我将把 BackgroundWorker 放在什么类中?
    • 我已经有一段时间没有使用 ole BackgroundTask 做了很多事情了,但希望一些代码可以帮助您朝着正确的方向前进。这在我的脑海中似乎是有道理的,但我并没有真正测试它。希望这个理论是正确的。
    【解决方案4】:

    您的应用没有响应吗?试试这个:

        public void ProressBarMovement()
        {
            progressBar1.PerformStep();
            Application.DoEvents();
        }
    

    【讨论】:

    • 试过了,应用正在响应进度条只是没有填写
    • 试试:this.Update();之前 Application.DoEvents();
    【解决方案5】:

    您应该像这样将进度条增量调用移动到 foreach 循环中:

     foreach (DataRow dr in dsImport.Tables[0].Rows)
    {
             //Code cgoes here 
             pb.ProressBarMovement();
    }
    

    这样每次您完成处理一行时,进度条都会更新一个,向用户显示处理行的整体进度。如果您只在最后这样做,您最终只会将进度条增加 1,这将显示不准确的进度并使其看起来好像没有移动

    【讨论】:

    • 真的很抱歉上面的代码示例有点不对 pb.ProressBarMovement();在foreach循环中
    • 是的,这就是重点,您将进度条的最大值设置为行数,这意味着每次处理一行时,您需要将进度条增加 1,直到您处理所有行。这就是为什么它应该在 for 循环中,以便向用户显示处理行的整体进度。如果你只在最后这样做,你最终只会将进度条增加 1,这将显示不准确的进度
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多