Обновить ProgressBar в другом окне из функции? - PullRequest
4 голосов
/ 05 сентября 2011

У меня есть фоновая задача, которая загружает файл, и я хочу, чтобы он сообщал о прогрессе на индикатор выполнения в другой форме. Как бы я пошел об этом? Я немного новичок в C #, но долгое время программист VB .net.

Я возился с этим кодом, но он совершенно неправильный.

System.Windows.Forms.Form progForm = new ProgressWindows();
Control[] ctrls = progForm.Controls.Find("fileProgress1", true);

Ответы [ 3 ]

2 голосов
/ 05 сентября 2011

Если вы используете BackgroundWorker , просто позвоните ReportProgress . В противном случае вам нужно будет отправить изменение пользовательского интерфейса в правильный поток. В WinForms см. Свойство Control.InvokeRequired и связанные методы. Эквивалентом WPF является DispatcherObject.VerifyAccess .

Edit: Visual Studio не передо мной, поэтому могут быть небольшие ошибки компиляции.

public partial class MyForm : Form
{
    public MyForm()
    {
        InitializeComponent(); // fileProgress1 setup. 
    }

    private void StartTask()
    {
        Task t1 = new Task(BackgroundMethod1, fileProgress1); // Explicitly pass a reference to the progress bar.
        Task t2 = new Task(BackgroundMethod2); // Use a method that has access to the bar.
        Task t5 = new Task(BackgroundMethod3, IncrementPBMethod); // Pass an action to the background method. Abstracting the physical progress bar as something where you can set the progress.
        Task t4 = new Task(delegate() { /* fileProgress1 referened*/ }); // Create a closure. I don't recommend this method.
    }

    private static void BackgroundMethod1(ProgressBar pb)
    {
        for(int i = 0; i < 100; ++i)
        {
            if(pb.InvokeRequired)
            {
                pb.Invoke(delegate() { pb.Value = i; });
            }

            Thread.Sleep(1000);
        }
    }

    private void BackgroundMethod2()
    {
        for(int i = 0; i < 100; ++i)
        {
            if(fileProgress1.InvokeRequired)
            {
                fileProgress1.Invoke(delegate() { fileProgress1.Value = i; });
            }

            Thread.Sleep(1000);
        }
    }

    private static BackgroundMethod3(Action<int> setProgress)
    {
        for(int i = 0; i < 100; ++i)
        {
            setProgress(i);
            Thread.Sleep(1000);
        }
    }

    private void IncrementPBMethod(int value)
    {
        if(fileProgress1.InvokeRequired)
        {
            fileProgress1.Invoke(IncrementPBMethod, value);
        }
        else
        {
            fileProgress1.Value = value;
        }
    }
}
1 голос
/ 05 сентября 2011

Если у вас проблема только с доступом к файлу Progress1. Самое простое решение - сделать его общедоступным в классе ProgressWindow. По умолчанию элементы управления являются частными.

enter image description here

Затем вы можете получить доступ к элементу управления fileProgress1, как показано ниже.

ProgressWindows progForm = new ProgressWindows();
//progForm.fileProgress1 

Однако лучшим способом является предоставление открытого метода в классе PrefressWindows, который обновляет прогресс.

В классе ProgressWindows

public void UpdateProgressBar(int percentage)
{
    // Set the progress in the progress bar.
    fileProgress1.Percentage = percentage;
}

Вызовите вышеуказанный метод, как показано ниже.

ProgressWindows progForm = new ProgressWindows();
progForm.UpdateProgressBar(percentage);
0 голосов
/ 05 сентября 2011

Я предполагаю, что ваша вторая форма (та, в которой вы хотите показать прогресс) создается в форме, выполняющей «задачу».Почему бы вам просто не создать открытый метод во второй форме, который исключает целочисленный параметр для обновления значения индикатора выполнения?Похоже на относительно простое решение.

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