ProgressBar исчезает при изменении из потока - PullRequest
0 голосов
/ 02 сентября 2011

Почему индикатор выполнения исчезает, когда стиль изменяется из потока, и как я могу избежать этого?

У меня есть поток, который работает неопределенное (но потенциально длительное) количество времени, поэтому я хотел использовать индикатор выполнения, чтобы отслеживать прогресс потока.Я установил стиль индикатора выполнения на выделение перед началом запуска потока, однако после завершения потока и установки стиля индикатора выполнения обратно на блоки (что можно сделать из другого потока, установив Form.CheckForIllegalCrossThreadCalls = false) индикатор выполнения исчезает изФорма визуально.Кроме того, если я добавлю кнопку в форму для ускоренного изменения стиля индикатора выполнения вперед и назад, он появится снова и изменит стиль назад и вперед при последовательном нажатии кнопки.

Ответы [ 4 ]

4 голосов
/ 02 сентября 2011

(что можно сделать из другого потока, установив Form.CheckForIllegalCrossThreadCalls = false)

Плохо.Плохо, плохо, плохо. Baaaaaaaad. Их называют незаконными вызовами между потоками по причине.

Единственный поток, из которого вам когда-либо нужно обновлять пользовательский интерфейс, - это поток пользовательского интерфейса.Без исключений.Чтобы достичь этого, вы должны либо использовать BackgroundWorker и вызвать метод ReportProgress (и обработать его с помощью ProgressChangedEventHandler, который гарантирует выполнениев потоке пользовательского интерфейса).

Если вы не используете BackgroundWorker, вы можете передать делегату с логикой, чтобы обновить индикатор выполнения для метода Invoke на вашеминдикатор выполнения, обеспечивающий выполнение кода в потоке пользовательского интерфейса.

4 голосов
/ 02 сентября 2011

Из замечаний MSDN по свойству CheckForIllegalCrossThreadCalls:

Когда поток, отличный от потока создания элемента управления, пытается доступ к одному из методов или свойств этого элемента управления, это часто приводит к непредсказуемые результаты. Обычная недопустимая активность потока - это вызов неправильный поток, который обращается к свойству Handle элемента управления. Задавать CheckForIllegalCrossThreadCalls в true, чтобы найти и диагностировать это активность потоков во время отладки.

Обычно считается плохой практикой обращаться к элементу управления из потока, отличного от потока пользовательского интерфейса, и обычно это не разрешается.

Вместо этого вам следует взглянуть на метод Control.Invoke. Я обычно обрабатываю обновления интерфейса с несколькими потоками, как это:

public void UpdateProgressBar(int NewValue) 
{
   if(InvokeRequired)
      Invoke(() => UpdateProgressBar(NewValue));
   else
      progressBar.Value = NewValue;
}

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

1 голос
/ 02 сентября 2011

Ух ты!Держитесь подальше от CheckForIllegalCrossThreadClass.Это свойство, хотя Microsoft и сделало его доступным, и я уверен, что есть очень, очень, очень редкое (и я имею в виду редкое ) использование, никогда не трогайте его.Это буквально принесет вред вашему программному обеспечению.

Вы можете использовать простой подход ISyncronizeInvoke для обновления вашего пользовательского интерфейса, , который я также написал в блоге на (очень простой).

/// <summary>
/// Helper class that allows synchronized invoking to be performed in a single line of code.
/// </summary>
internal static class SynchronizedInvoke {
    /// <summary>
    /// Invokes the specified action on the thread that the specified sync object was created on.
    /// </summary>
    public static void Invoke(ISynchronizeInvoke sync, Action action) {
        if (!sync.InvokeRequired) {
            action();
        }
        else {
            object[] args = new object[] { };
            sync.Invoke(action, args);
        }
    }
}

Использование просто.

private void MyThreadWork() {
    // Do some work
    SynchnronizeInvoke.Invoke(uxProgressBar, () => uxProgressBar.Style = ProgressBarStyles.Blocks);
}
1 голос
/ 02 сентября 2011

Честно говоря, я никогда не слышал о Form.CheckForIllegalCrossTHreadCalls , но документация гласит:

Когда поток, отличный от создающего потока элемента управления, пытается доступ к одному из методов или свойств этого элемента управления, это часто приводит к непредсказуемые результаты. Обычная недопустимая активность потока - это вызов неправильный поток, который обращается к свойству Handle элемента управления.

Установите для CheckForIllegalCrossThreadCalls значение true, чтобы найти и диагностировать это упрощение работы потоков во время отладки.

Вы, установив его в false, просто говорите «заткнись» на проблему, которую ты поднимаешь.

Вы не можете изменить управление из потока, отличного от пользовательского интерфейса. Так что не используйте это свойство. Просто используйте Invoke формы для запуска кода в главном потоке.

SO Пример

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