【问题标题】:c# Progress Bar calling methods from another classc#进度条从另一个类调用方法
【发布时间】:2011-10-31 14:03:08
【问题描述】:

我试图通过公开两个方法然后从另一个类调用方法来使 WinForm 上的进度条工作(请参阅下面的代码示例)。但运气不好,条形图不动。

这是两个类:

namespace GP_Avantis_Integration
{
    //Class B
    public partial class GP_Avantis_Integration_Window : Form
    {
        public GP_Avantis_Integration_Window()
        {
            InitializeComponent();
        }

        DataSet ds = new DataSet();
        SqlDataAdapter sqlda = new SqlDataAdapter();
        SqlCommand sqlcomm = new SqlCommand();

        public static int recno;

        public void button1_Click(object sender, EventArgs e)
        {
            try
            {
                //Fetch data into memory

                //Fill in Header table

                //Fill in Line table

                //Cleaning open connection

                //Creating relationship in the Dataset between Header and Line table

                // Instantiating and Crearintg Header and Line source

                //Binding the Header source to the Header table

                //Binding the Line source to the relationship
            }

            catch (ApplicationException ae)
            {
            }

            finally
            {
            }
        }

        public void button2_Click(object sender, EventArgs e)
        {
            try
            {

                //Calling CreateJE Class
                //Class Method ProcessData
                CreateJE JE = new CreateJE(); --------> Calls the Class B
                JE.ProcessData(ds);
                MessageBox.Show("Complete!");
            }

            catch (ApplicationException ae)
            {
            }

            finally
            {
            }
        }

        public void progress_Bar_setup()
        {
            progressBar1.Minimum = 0;
            progressBar1.Maximum = CreateJE.max;
        }

        public void progressBar_updates(int recno)
        {
            progressBar1.Value = recno;
            progressBar1.Update();
        }
    }

    // Class B
    class CreateJE
    {
        static public int max;
        public void ProcessData (DataSet ds)
        {
            //Create an eConnect Trx type object
            //POPTransactionType po = new POPTransactionType();

            // ***** PO Header and Line 

            int ln;
            ln = 0;

            //Setting up ProgressBar
            int recno = 1;
            max = ds.Tables[0].Rows.Count;

            GP_Avantis_Integration_Window w = new GP_Avantis_Integration_Window();
            w.progress_Bar_setup();

            // Create an eConnect PO Header node object

            // Create an array for lineitems

            foreach (DataRow dtrHDR in ds.Tables["Header"].Rows)
            {
                //ProgressBar Updates
                w.progressBar_updates(recno);

                //Instantiating GetJE object 
                //Retrieves the next JE from GP

                //Create an eConnect PO Header node object

                //Add the header node to the trx type object

                ln = 0;

                foreach (DataRow dtrLine in dtrHDR.GetChildRows("HdrLine"))
                {
                    // Populate the elements of the taPoLIne_ItemsTaPOLine XML node

                    //Avantis Inv Trx Key

                    // Avantis GL Trx Type

                    //Add POLine to an Array

                    ln ++;
                }

                // Add the header node to the trx type object

                // Add the lineitem node to the trx type object

                // ***** Process information only

                // Create an eConnect document object

                // Create a file on the HD

                // Serialize using the XmlTextWriter to the file

                // Call the eConnectMethods
                // Separate Class

                // Instantiating the object for eConnectMethods class
                // Passing last JRNENTRY retreived using the GetJE class
                // so if there is an error on the eConnectEntry Method of     eConnectMethods Class
                // I can pass the last JE number back to GP

                recno++;
            }  
        }
    }
}

【问题讨论】:

  • 出了什么问题? progesbar1.value 是否在调试时发生变化?如果是这样,您可能需要在后台线程中启动 foreach 循环。
  • 您将无法通过使用对进度条的引用来调用连接到 B 类的属性或方法。发布实际代码,您的示例代码,甚至不是有效代码。这时候除非你贴出可以实际编译的代码,否则帮不上忙,请解释清楚什么是行不通的。
  • 我正在设置 min=0,max=2。在 B 类中使用 foreach 循环将 1 和 2 的值传递给 progressbar1.update() 方法。调试时我可以看到正在传递的值。进度条(视觉上)没有移动。
  • 我想你在哪里展示你的表格?您在上面为 B 类显示的代码声明了一个 WinForm 的新实例,但它似乎没有调用该表单的 Show 方法。您是否以某种方式将 A 类的实例传递给 B 类?您似乎正在 B 类中创建 WinForm 的新实例并尝试更新该实例而不是现有实例。但是您发布的代码并未显示这一点。这就是为什么展示一个可以编译的简短而完整的程序很重要!
  • 我包含了完整的代码和一些编辑。希望这会有所帮助。

标签: c# winforms progress-bar


【解决方案1】:

很难说是什么问题。可能是max 值没有被初始化,可能是update() 方法没有重绘进度条。

还有一件事:使用 BackgroundWorker 可能会更好,这样您的 UI 就不会锁定?这是一个例子:http://www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo

【讨论】:

  • 调试时我在progressbar1.update() 上得到{value=1, min=0, max=2} 值。所以看起来值被正确传递了。
【解决方案2】:

我认为您需要使用渲染优先级调用更新,如下所示:

 public void progressbar_updates(int recno)
 {
     Dispatcher.Invoke(new Action(() =>
     {
              progressbar1.Value += recno;
              progressbar1.UpdateLayout();
     }), DispatcherPriority.Render);
 }

【讨论】:

  • 调度程序是 WPF。 OP 说他正在使用 WinForms。
【解决方案3】:

实现一个 backgroundWorker 并使用backgroundworker.ReportProgress 来更新进度条。然后它将在一个线程中实现您的代码,并在另一个线程中实现 UI。然后表单将响应更新。读取和写入 UI 时要小心(因为它在另一个线程中)在启动 Backgroundworker 并写入 ReportProgress 时重新读取 UI。

C# Winform ProgressBar and BackgroundWorker

【讨论】:

    【解决方案4】:

    使用后台工作人员。
    这是最好的例子
    Click here for BackGroundWorker

    【讨论】:

      【解决方案5】:

      我实现了一个显示后台任务进度的“工人表单”。

      这是我的代码 (WorkerForm)

              #region Form
          private void frmLoader_Load(object sender, EventArgs e)
          {
                          if (OnExecute != null)
              {
                  OnExecute(this, null);
              }
          }
          #endregion
          #region "Public"
          public void OnInitialize(object sender, EventArgs<String, int> e)
      {
        if (pbLoader.InvokeRequired)
        {
          pbLoader.Invoke(new Action<object, EventArgs<String, int>>(OnInitialize), new Object[] { sender, e });
        }
        else
        {
          lblDynamicText.Text = e.Param1;
          pbLoader.Step = 1;
          pbLoader.Minimum = 1;
          pbLoader.Value = 1;
          pbLoader.Maximum = e.Param2;
        }
      }
      public void OnCreate(object sender, EventArgs<String> e)
      {
        if (lblDynamicText.InvokeRequired)
        {
          lblDynamicText.Invoke(new Action<object, EventArgs<String>>(OnCreate), new Object[] { sender, e });
        }
        else
        {
          lblDynamicText.Text = e.Param1;
          pbLoader.PerformStep();
        }
      }
      public void OnFinished(object sender, EventArgs<String> e)
      {
        if (lblDynamicText.InvokeRequired)
        {
          lblDynamicText.Invoke(new Action<object, EventArgs<String>>(OnFinished), new Object[] { sender, e });
        }
        else
        {
          lblDynamicText.Text = e.Param1;
        }
      }
      

      在我的演示者中(我使用的是 ModelViewPresenter 架构),我同时注入了对 Winform 和实际工作类的引用。

       internal WorkerPresenter(IWorkerView WorkerView,IWorker ConcreteWorker)
      {
        this.WorkerView = WorkerView;
        this.ConcreteWorker = ConcreteWorker;
        WorkerView.OnExecute += StartExecute;
      }
      

      在我的 Worker Form 的 Form Load Event 期间引发 StartExecute。

      private void StartExecute(Object sender, EventArgs e)
      {
        ConcreteWorker.OnCreate += Create;
        ConcreteWorker.OnFinish += Finished;
        ConcreteWorker.OnInitialize += Initialize;
          var task = new Task<bool>(ConcreteWorker.Execute);
          task.Start();
          task.ContinueWith(c_task =>
          {
            ((frmWorker)WorkerView).DialogResult = System.Windows.Forms.DialogResult.OK;
          });
      }
      

      IWorker 接口:

        public interface IWorker  {
      event EventHandler<EventArgs<String>> OnCreate;
      event EventHandler<EventArgs<String>> OnFinish;
      event EventHandler<EventArgs<String, int>> OnInitialize;
      bool Execute();
      

      }

      Concrete Worker: OnInitialize => 在进度条中设置文本和步数。 OnCreate => 将计步器加一并设置另一个文本。 OnFinish => 显示一个文本并再次关闭 Worker 表单。

      【讨论】:

        猜你喜欢
        • 2015-10-30
        • 2020-10-20
        • 2014-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-17
        • 2013-02-17
        • 1970-01-01
        相关资源
        最近更新 更多