Поток с модальной формой выполнения, не удается обновить свойство текста метки

У меня есть форма Windows Form, которая является модальным дочерним элементом mdi, который, как предполагается, будет отображаться при интенсивной фоновой работе, поэтому пользователь не может использовать какие-либо элементы управления, пока эта работа не будет завершена.

Это очень просто, вот код.

public partial class ProgressForm : Form
{
    private int periodCount = 5;

    public ProgressForm(String message)
    {
        InitializeComponent();
        messageLabel.Text = message;
    }

    public void startThread()
    {
        Thread t = new Thread(new ThreadStart(doWork));
        t.IsBackground = true;
        t.Start();
    }

    void doWork()
    {
        while (true)
        {
            if (periodCount == 5)
            {
                periodCount = 1;
            }
            else
            {
                periodCount++;
            }

            switch (periodCount)
            {
                case 1: periodsLabel.Text = "."; break;
                case 2: periodsLabel.Text = ". ."; break;
                case 3: periodsLabel.Text = ". . ."; break;
                case 4: periodsLabel.Text = ". . . ."; break;
                case 5: periodsLabel.Text = ". . . . ."; break;
            }
        }
    }
}

но периодыLabel.Text не меняются, как предполагалось! Как мне заставить его обновлять пользовательский интерфейс, делая что-то еще в фоновом режиме?

ProgressForm progressForm = new ProgressForm("Your database data is being exported, please wait.");
progressForm.ShowDialog();
progressForm.startThread();

person CODe    schedule 18.12.2010    source источник
comment
Есть ли у вас какие-либо подробности об исключениях из этих сбоев?   -  person Jay    schedule 18.12.2010
comment
Программа просто перестает отвечать. Я думал, что это был особенно изящный способ делать что-то, но я полагаю, что нет.   -  person CODe    schedule 18.12.2010
comment
+1 Дебют многопоточности всегда неприятен для любого, кто начинает ее использовать. Любая полезная информация приветствуется для тех, кто еще не прошел. знак равно   -  person Will Marcouiller    schedule 18.12.2010


Ответы (2)


Во-первых, по моему скромному мнению, вы не должны просто выбрасывать нить, как вы.

Лучше всего использовать поток BackgroundWorker.

Во-вторых, ваша форма вообще не является модальной, поскольку вы показываете ее только с помощью _ 2_. Чтобы сделать его модальной формой, вам нужно сделать его диалогом, используя _ 3_.

Что касается того, почему именно ваша Форма дает сбой, то теперь это выходит за рамки нашей компетенции. Пожалуйста, рассмотрите следующие шаги:

  1. Создайте экземпляр класса BackgroundWorker;
  2. Заставьте метод BackgroundWorker.DoWork() сделать за вас грязную работу;
  3. Убедитесь, что вы установили BackgroundWorker.WorkerReportsProgress = true в окне свойств модели компонента в проекте;
  4. Убедитесь, что вы ReportProgress() используете метод ReportProgress(int).

См. этот вопрос (C #: заполнение пользовательского интерфейса с помощью отдельные потоки.) и мой пример кода, который, как мне кажется, просто объясняет использование экземпляра класса BackgroundWorker.

Примечание. Все еще ищу другой пример.

ИЗМЕНИТЬ №1

Вот хорошая статья о потоках: Threading в C #.
Потому что Jon Skeet так сказал! Многопоточность в .NET: введение и предложения .

person Will Marcouiller    schedule 18.12.2010
comment
Имейте в виду, что при обновлении каких-либо элементов управления в потоке, отличном от потока, в котором был создан элемент управления, вам необходимо делегировать обратно потоку, в котором он был создан. Используйте Control.InvokeRequired, чтобы определить, так ли это, и вызовите Control.Invoke (), если это необходимо. Вот статья msdn об использовании Invoke: msdn.microsoft.com/en-us /library/a1hetckb.aspx - person Brian Ball; 18.12.2010
comment
Черт побери, эта фигня всегда меня до чертиков смущала. - person CODe; 18.12.2010
comment
Чтобы преодолеть кривую обучения использованию потоков, не нужно много времени. Если вы используете .NET 3.5 или новее, вам не нужно создавать делегат, вместо этого вы можете передать лямбда-функцию. - person Brian Ball; 18.12.2010
comment
А, можно ссылку на статью об этом? А пока я попробую погуглить, чтобы посмотреть, смогу ли я что-нибудь найти ... - person CODe; 18.12.2010
comment
@Will: Большое спасибо за ваш вклад. Я проведу еще несколько исследований и проверю, и я уверен, что все выясню. :) - person CODe; 18.12.2010
comment
@CODe: Удалось ли вам поработать вместе с классом BackgroundWorker и вашим ProgressForm? - person Will Marcouiller; 19.12.2010

Вероятно, что ваше приложение вылетает из-за того, что вы пытаетесь получить доступ к свойствам элементов формы непосредственно из потока (например, когда вы вызываете PeriodsLabel.Text), а не используете BeginInvoke из вашего потока для вызова метода в вашей форме, который будет выполнять свойство доступ.

Но лучше / проще использовать класс BackgroundWorker для такого рода вещей.

person Tola Odejayi    schedule 18.12.2010