реализация индикатора выполнения, чтобы показать работу - PullRequest
0 голосов
/ 24 июня 2011

У меня есть одна форма 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++;    
    }   
}

Как это можно сделать?

Ответы [ 4 ]

2 голосов
/ 24 июня 2011

Эти функции не должны обновлять индикатор выполнения - это нарушает принцип единственной ответственности. Вам лучше использовать фонового работника или просто обновлять индикатор выполнения из вашего события button_click после каждого вызова функции.

1 голос
/ 24 июня 2011

Если вы делаете что-то, что занимает так много времени, вы должны показать индикатор выполнения, тогда вы должны делать это в фоновом потоке, а не в форме.Это приведет к тому, что пользовательский интерфейс перестанет отвечать на запросы.

Проект кода Тема BackgroundWorker содержит пример фонового потока, который отображает индикатор выполнения в приложении WinForms.

1 голос
/ 24 июня 2011

Самый простой способ сделать это - просто вызвать 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;
    }

}
0 голосов
/ 24 июня 2011

В прошлом я использовал простую форму без строки меню с меткой и формой 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);

Это не самый элегантный метод, но он дает вам четко обновляемый индикатор выполнения в отдельном потоке, который будет реагировать, пока вы с ним возитесь. Я в значительной степени скопировал и вставил весь этот код из рабочего приложения, поэтому оно должно работать. С другой стороны, я прошу прощения, если что-то из этого неясно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...