2011-06-24 33 views
0

我有一个表格Form1,它包含两个元素按钮和进度条。 当我点击按钮时,它会调用class.SomeFunction(),然后调用其他几个类来完成一些工作。实施进度条显示正在进行的工作

我想提高进度条的值从内class.SomeFunctin()和所有其他职能SomeFunctino呼叫

class @class 
{ 
    public static void SomeFunction(var something) 
    { 
     progressbar.value++; 
     class2.Function2(something);  
    } 
} 

class class2 
{ 
    public static void Function2(var something) 
    { 
     progressbar.value++;  
    } 
} 

如何才能做到这一点?

+0

我认为如果你的功能是静态的,你会遇到麻烦。我将提供一个没有“非静态”工作者的例子。 –

回答

2

你真的不应该有这些功能更新进度栏 - 它违反了单一责任原则。在每次函数调用之后,最好使用backgroundworker或在button_click事件中更新进度条。

0

在过去我用一个简单的菜单栏,少形式的标签和使用形式下面的代码就可以了Forms.ProgressBar:

public partial class ProgressDialog : Form 
{ 
    //public delegate delSetProgress 
private readonly int progressBarMax; 

/// <summary> 
/// Structure used for passing progress bar related parameters as a single variable. 
/// </summary> 
public struct ProgressBarParams 
{ 
    public int value; 
    public string message; 

    public ProgressBarParams(string Message, int Value) 
    { 
     message = Message; 
     value = Value; 
    } 
} 

/// <summary> 
/// Constructs the progress bar dialog and sets the progress bar's maximum value to maxValue. 
/// </summary> 
/// <param name="maxValue">Value to set to progress bar's Maximum property.</param> 
public ProgressDialog(int maxValue) 
{ 
    InitializeComponent(); 
    progressBarMax = maxValue; 
} 

private void ProgressDialog_Load(object sender, EventArgs e) 
{ 
    progressBar.Maximum = progressBarMax; 
} 

/// <summary> 
/// Public method to update the progressDialog 
/// </summary> 
/// <param name="inputParams">Values to update on the progressDialog</param> 
public void SetProgress(ProgressBarParams inputParams) 
{ 
    lblMessage.Text = inputParams.message; 
    progressBar.setValue(inputParams.value); 
    Update(); 
} 

/// <summary> 
/// This method should be called when the operation represented by the ProgressDialog is 
/// completed. It shows an "operation complete" message for a second and then closes the form. 
/// </summary> 
public void Finish() 
{ 
    lblMessage.Text = "Operation complete."; 
    progressBar.setValue(progressBar.Maximum); 
    Update(); 
    System.Threading.Thread.Sleep(1000); 
     this.Close(); 
    } 
} 

public static class MyExtensions 
{ 
    /// <summary> 
    /// Implements a hack to get around a stupid rendering problem with the .NET progress bar in some environments. 
    /// Sets the progress bar value property. 
    /// </summary> 
    /// <param name="proBar">Progress bar control to set the value on.</param> 
    /// <param name="value">Value to be set.</param> 
    public static void setValue(this ProgressBar proBar, int value) 
    { 
     if (value > 0) 
     { 
      proBar.Value = value; 
      proBar.Value = value - 1; 
      proBar.Value = value; 
     } 
     else 
     { 
      proBar.Value = value; 
      proBar.Value = value + 1; 
      proBar.Value = value; 
     } 
    } 
} 

注意setValue扩展方法使用避免某些版本的Windows出现问题的解决方法。

我再设置它(闪屏)了以下内容,其中m_frmProgress是进度条形式:

 // Create splash screen/progress bar thread on the thread pool 
     ThreadPool.QueueUserWorkItem((x) => 
     { 
      bool localDone = false; 
      m_frmSplash.Show(); 
      m_frmProgress.Show(); 
       // Set the progress bar form up slightly below the bottom of the splash screen 
       m_frmProgress.Location = new Point(m_frmProgress.Location.X, m_frmProgress.Location.Y + (m_frmSplash.Height/2) + (m_frmProgress.Height/2) + 10);  

       while (!localDone) // Keep iterating until the main thread tells us we're done 
       { 
        lock (splashScreenDoneLock) 
        { 
         localDone = splashScreenDone; 
        } 
        // I don't like this method of keeping the UI responsive, but as yet I have no better method 
        Application.DoEvents(); 
        Thread.Sleep(500); 
       } 
       m_frmSplash.Close(); 
       m_frmProgress.Close(); 
       while (!m_frmProgress.IsDisposed || !m_frmSplash.IsDisposed) // While either splash form is not disposed (still active) 
       { 
        Thread.Sleep(100); // Keep waiting until the splash forms are gone 
       } 
       splashFormsDisposed.Set(); // Signal the main thread that the splash forms are gone so the main form can be shown 
      }); 

      bool isSplashHandleCreated = false; 
      bool isProgressHandleCreated = false; 

      // Wait until both splash forms are created 
      while (!(isSplashHandleCreated && isProgressHandleCreated)) 
      { 
       lock (m_frmSplash) 
       { 
        isSplashHandleCreated = m_frmSplash.IsHandleCreated; 
       } 
       lock (m_frmProgress) 
       { 
        isProgressHandleCreated = m_frmProgress.IsHandleCreated; 
       } 
       Thread.Sleep(500); 
      } 

并调用它像这样:

m_frmProgress.Invoke(new Action<ProgressDialog.ProgressBarParams>(m_frmProgress.SetProgress), progressLevel); 

这不是最优雅的方法,但它会给你一个干净的可更新进度条,在一个单独的线程上保持响应,当你搞砸它时。我几乎复制并粘贴来自工作应用程序的所有代码,所以它应该可以工作。另一方面,如果有任何不清楚的地方,我表示歉意。

1

要做到这一点,最简单的方法就是调用在表单中处理的event,并在事件处理函数中增加进度条。

你首先要做的是创建一个自定义EventArgs

public class ProgressEventArgs : EventArgs 
{ 
    public int Progress {get; set;} 
    public ProgressEventArgs(int progress) 
    { 
     Progress = progress; 
    } 
} 

然后在您希望增加进度条的课程中,您将要引发此事件。

class Class2 
{ 
    public event EventHandler<ProgressEventArgs> ProgressEvent; 

    public void Function2(var something) 
    { 
     OnRaiseProgressEvent(new ProgressEventArgs(1)); 
    } 

    protected virtual void OnRaiseProgressEvent(ProgressEventArgs e) 
    { 
     // C# 6 and above: 
     // Raise event if event handler is set (i.e. not null) 
     ProgressEvent?.Invoke(this, e); 
     // end C# >=6 code 

     // C# 5 and earlier: 
     EventHandler<ProgressEventArgs> handler = ProgressEvent; 

     if(handler != null) 
     { 
      //this is what actually raises the event. 
      handler(this, e); 
     } 
     // end C# <=5 code 
    } 
} 

然后在您的形式,你会想订阅的事件

public class YourForm 
{ 
    public YourForm 
    { 
     Class2 yourClass2Instance = new Class2(); 
     yourClass2Instance.ProgressEvent += ProgressEventHandler; 
    } 

    private void ProgressEventHandler(object sender, ProgressEventArgs e) 
    { 
     progressbar.Value += e.Progress; 
    } 

} 
1

如果你正在做的事情需要这么长时间,你必须显示一个进度条,那么你应该在做后台线程而不是表单。这会让用户界面变得无法响应。

一个代码项目BackgroundWorker Thread文章有一个后台线程,显示在一个WinForms应用程序的进度条的例子。