C# обновляют и добавляют значение текстового поля с помощью backgroundworker процесс

У меня есть c# приложение форм окон, которое я бросил вместе. Это справедливо simple:\

исходные данные:

  • текстовая строка
  • исходный путь к папке
  • путь папки назначения
  • целочисленное количество

Приложение перерывает текстовые файлы в исходной папке для строки введенного текста; если это находит строку затем, это копирует тот файл и файл изображения с тем же именем к папке назначения. Это делает это однако много раз на основе целого числа вводило.

Таким образом, у меня есть кнопка, и в событии нажатия кнопки я звоню

ProcessImages(tbDID.Text, tbSource.Text, tbDest.Text, comboBoxNumberImages.SelectedItem.ToString());

который является:

private void ProcessImages(string DID, string SourceFolder, string DestFolder, string strNumImages)
        {         
            int ImageCounter = 0;
            int MaxImages = Convert.ToInt32(strNumImages);

            DirectoryInfo di = new DirectoryInfo(SourceFolder);

            foreach (FileInfo fi in di.GetFiles("*.txt"))
            {
                if (fi.OpenText().ReadToEnd().Contains(DID))
                {
                    //found one!
                    FileInfo fi2 = new FileInfo(fi.FullName.Replace(".txt", ".tif"));
                    if (fi2.Exists)
                    {
                        try
                        {
                            tbOutput.Text += "Copying " + fi2.FullName + " to " + tbDest.Text + "\r\n";
                            fi2.CopyTo(tbDest.Text + @"\" + fi2.Name, true);
                            tbOutput.Text += "Copying " + fi.FullName + " to " + tbDest.Text + "\r\n";
                            fi.CopyTo(tbDest.Text + @"\" + fi.Name, true);

                            ImageCounter++;
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                        }
                    }
                }

                if (ImageCounter >= MaxImages)
                    break;

            }

        }

То, что происходит, - то, что процесс хорошо работает, но я хочу обновить текстовое поле на форме с прогрессом, поскольку файлы копируются. В основном форма потеряла сознание, в то время как она работает, и после того, как она закончилась, вывод находится в текстовом поле. Я хотел бы реализовать BackgroundWorker, заставляют это обновлять UI, в то время как это работает.

Я просмотрел примеры, но действительно не следую за ними. У меня нет процента полным значением, я просто хочу обновить изменения.Text каждое повторение и иметь его дисплей. Я даже не думаю, что обязательно должен поместить фактическое действие копирования в различные потоки, оно просто кажется, что потребности, которые будут выполнены отдельно от основного UI, распараллеливают. Возможно, я по усложнению этого, в целом... кто-то может продвинуть меня в правильном направлении?Спасибо!

14
задан Peter Tirrell 21 July 2010 в 19:15
поделиться

4 ответа

Если вы используете фоновый рабочий процесс, вы можете использовать метод ReportProgress для возврата любого целого числа, например количества обработанных записей. Это не обязательно должен быть процент. Затем в обработчике ProgressChanged вы можете обновить текстовое поле. Например.

int count = e.ProgressPercentage;
textBox1.Text = string.Format("{0} images processed.", count);

Если вы не хотите использовать фонового рабочего, вы можете вызвать Application.DoEvents () внутри своего цикла. Это даст возможность пользовательскому интерфейсу обновляться и реагировать на действия пользователя. Но будьте осторожны - это сильно замедлит вашу программу, поэтому вы можете вызывать ее только на каждой сотой итерации.

7
ответ дан 1 December 2019 в 12:12
поделиться

Вы на правильном пути с фоновым рабочим. Вот пример, который я собрал, чтобы показать вам, как это сделать. Создайте новое приложение windows с формой Form1. Добавьте к ней 4 элемента управления: label1, backgroundWorker1, button1 и button2. Затем используйте этот code-behind. Затем вы можете использовать пользовательское состояние ReportProgress, чтобы сообщать главному потоку все, что захотите. В этом примере я передаю строку. Обработчик события ProgressChanged затем находится в потоке UI и обновляет текстовое поле.

    public partial class Form1 : Form
{
    int backgroundInt;
    public Form1()
    {
        InitializeComponent();
        backgroundWorker1.WorkerReportsProgress = true;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        label1.Text = e.UserState as string;
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        backgroundInt = 1;
        while (backgroundWorker1.CancellationPending == false)
        {
            System.Threading.Thread.Sleep(500);
            backgroundWorker1.ReportProgress(0, 
                String.Format("I found file # {0}!", backgroundInt));
            backgroundInt++;
        }
    }


    private void button1_Click(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        backgroundWorker1.CancelAsync();
    }
}
14
ответ дан 1 December 2019 в 12:12
поделиться

Пользовательский интерфейс не обновляется, потому что вы не разрешаете обрабатывать какие-либо оконные сообщения в длительном цикле обработки файлов. Приложения WinForms перерисовываются в ответ на сообщения WM_PAINT, которые обрабатываются в очереди сообщений в основном потоке.

Простейшее решение - принудительное обновление пользовательского интерфейса: попробуйте вызвать Update () в форме после изменения текстового поля внутри цикла.

Пользовательский интерфейс вашего приложения по-прежнему будет зависать (не реагировать на щелчки мыши и т. Д.), Но это должно, по крайней мере, отображать сообщения о ходе выполнения на экране. Если обновление дисплея - это все, что вам действительно нужно, остановитесь здесь.

Следующий уровень решения - позволить вашему приложению обрабатывать ожидающие оконные сообщения в вашем цикле обработки файлов. Вызовите Application.DoEvents () в своем цикле (вместо form.Update). Это позволит форме перерисовываться вместе с обновлениями вывода текста и устранит зависание пользовательского интерфейса - приложение может реагировать на действия мыши и клавиатуры.

Однако будьте осторожны - пользователь может щелкнуть кнопку, которая запустила текущее действие, в то время как текущее действие выполняется - повторный вход. Вы должны как минимум отключить меню или кнопку, которая запускает длительную обработку файла, чтобы предотвратить повторный вход.

Третий уровень решения - использовать фоновый поток для обработки файла. Это приводит к появлению целого ряда новых проблем, о которых вам необходимо знать, и во многих случаях потоков оказывается излишним. Нет особого смысла переносить обработку файла в фоновый поток, если вы не собираетесь позволять пользователю делать что-либо еще с вашим приложением во время обработки файла.

2
ответ дан 1 December 2019 в 12:12
поделиться

Просто создайте (1) делегат, чтобы обернуть вызов метода ProcessImages, (2) запустите вызов с помощью делегата, и (3) когда вы захотите обновить textbox из метода ProcessImages, проверьте работу перекрестного потока и убедитесь, что вы делаете обновление из главного потока:

delegate void ProcessImagesDelegate(string did, string sourceFolder, string destFolder, string strNumImages);

private void ProcessImages(string DID, string SourceFolder, string DestFolder, string strNumImages)
{
    // do work

    // update textbox in form
    if (this.textBox1.InvokeRequired)
    {
        this.textBox1.Invoke(new MethodInvoker(delegate() { this.textBox1.Text = "delegate update"; }));
    }
    else
    {
        this.textBox1.Text = "regular update";
    }

    // do some more work
}

public void MyMethod()
{
    new ProcessImagesDelegate(ProcessImages).BeginInvoke(tbDID.Text, tbSource.Text, tbDest.Text, comboBoxNumberImages.SelectedItem.ToString(), null, null);
}
1
ответ дан 1 December 2019 в 12:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: