繁体   English   中英

单独线程上的进度条未更新

[英]Progress bar on separate thread not updating

在我的项目中,我有一个Form ,如“任务对话框”,它显示在自己的线程上...这样,当主线程锁定时,仍可以更新任务对话框的ProgressBar和状态。 我的问题是ProgressBar没有更新。 状态文本会更新,但是ProgressBar直到Form关闭之前才会移动。 Form正在主线程中打开。 这是我的代码:

public partial class TaskForm : Form
{
    /// <summary>
    /// Gets or Sets whether the task is cancelable
    /// </summary>
    protected bool Cancelable = true;

    /// <summary>
    /// Returns whether the Task form is already open and running
    /// </summary>
    /// <returns></returns>
    public static bool IsOpen
    {
        get { return (Instance != null && !Instance.IsDisposed); }
    }

    /// <summary>
    /// The task dialog's instance
    /// </summary>
    private static TaskForm Instance;

    /// <summary>
    /// Private constructor... Use the Show() method rather
    /// </summary>
    private TaskForm()
    {
        InitializeComponent();
    }

    /// <summary>
    /// Open and displays the task form.
    /// </summary>
    /// <param name="Parent">The calling form, so the task form can be centered</param>
    public static void Show(Form Parent, string WindowTitle, string InstructionText, string SubMessage, bool Cancelable, ProgressBarStyle Style)
    {
        // Make sure we dont have an already active form
        if (Instance != null && !Instance.IsDisposed)
            throw new Exception("Task Form is already being displayed!");

        // Create new instance
        Instance = new TaskForm();
        Instance.Text = WindowTitle;
        Instance.labelInstructionText.Text = InstructionText;
        Instance.labelContent.Text = SubMessage;
        Instance.Cancelable = Cancelable;
        Instance.progressBar.Style = Style;

        // Hide Cancel
        if (!Cancelable)
        {
            Instance.panelButton.Hide();
            Instance.Padding = new Padding(0, 0, 0, 15);
            Instance.BackColor = Color.White;
        }

        // Set window position to center parent
        double H = Parent.Location.Y + (Parent.Height / 2) - (Instance.Height / 2);
        double W = Parent.Location.X + (Parent.Width / 2) - (Instance.Width / 2);
        Instance.Location = new Point((int)Math.Round(W, 0), (int)Math.Round(H, 0));

        // Run form in a new thread
        Thread thread = new Thread(new ThreadStart(ShowForm));
        thread.IsBackground = true;
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        Thread.Sleep(100); // Wait for Run to work
    }

    /// <summary>
    /// Closes the Task dialog
    /// </summary>
    public static void CloseForm()
    {
        if (Instance == null || Instance.IsDisposed)
            throw new Exception("Invalid Operation. Please use the Show method before calling any operational methods");

        Instance.Invoke((Action)delegate()
        {
            Instance.Close();
        });
    }

    /// <summary>
    /// Runs the form in a new application, to prevent thread lock
    /// </summary>
    protected static void ShowForm()
    {
        Application.Run(Instance);
    }

    /// <summary>
    /// Updates the instruction text on the task dialog
    /// </summary>
    /// <param name="Message"></param>
    public static void UpdateInstructionText(string Message)
    {
        if (Instance == null || Instance.IsDisposed)
            throw new Exception("Invalid Operation. Please use the Show method before calling any operational methods");

        Instance.Invoke((Action)delegate()
        {
            Instance.labelInstructionText.Text = Message;
        });
    }

    /// <summary>
    /// Updates the detail text above the progress bar
    /// </summary>
    /// <param name="Message"></param>
    public static void UpdateStatus(string Message)
    {
        if (Instance == null || Instance.IsDisposed)
            throw new Exception("Invalid Operation. Please use the Show method before calling any operational methods");

        Instance.Invoke((Action)delegate()
        {
            Instance.labelContent.Text = Message;
        });
    }

    /// <summary>
    /// Updates the progress bar's value
    /// </summary>
    /// <param name="Percent"></param>
    public static void UpdateProgress(int Percent)
    {
        if (Instance == null || Instance.IsDisposed)
            throw new Exception("Invalid Operation. Please use the Show method before calling any operational methods");

        Instance.Invoke((Action)delegate()
        {
            Instance.progressBar.Step = Percent;
            Instance.progressBar.PerformStep();
            Instance.progressBar.Refresh();
        });
    }

    #region Non Static

    private void CancelBtn_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.Cancel;
        this.Close();
    }

    #endregion
}

当我调用UpdateStatusUpdateInstructionText方法时,文本更新是没有意义的,但是在调用UpdateProgress时, ProgressBar不会更新。 任何帮助将不胜感激。

通过查看代码,您可以在progressBar.Step属性的UpdateProgress()方法中传递百分比,该百分比指示调用PerformStep()时要增加的数量。

由于UpdateProgress()方法以百分比形式使用,我会把

Instance.progressBar.Step = Percent; 

进入静态Show()方法

...
Instance.progressBar.Style = Style;
Instance.progressBar.Step = Percent; 
...

您会看到它更新进度条的百分比。

我正在使用以下示例

TaskForm.Show(this, "Task is executing...", "Step 1 - Preparing...", 
                    "Runninig", true, ProgressBarStyle.Continuous);
for (int i = 1; i <= 100; i++)
{
  TaskForm.UpdateInstructionText("Step 1 - Executing..." + i );
  TaskForm.UpdateStatus("Running " + i);
  TaskForm.UpdateProgress(i);

  Thread.Sleep(1000);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM