2009-04-07 2 views
1

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

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

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

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

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

ответ

2

Следующий ответ основан на моем чувстве кишки и на самом деле не прошел тест с сторонними библиотеками.

  • Вызвать свой третий код lib, как обычно, вы вызываете в простой фоновом режиме (не BackGroundWorker).
  • Прикрепите события компонентов библиотеки к обычным обработчикам событий в вашем коде (для обновления интерфейса).
  • В коде обработчика событий должен выглядеть следующим образом:

    private void EventHandler(object sender, DirtyEventArgs e) 
    { 
        if (myControl.InvokeRequired) 
         myControl.Invoke(new MethodInvoker(MethodToUpdateUI), e); 
        else 
         MethodToUpdateUI(e); 
    } 
    
    private void MethodToUpdateUI(object obj) 
    { 
        // Update UI 
    } 
    
+0

С помощью метода Invoke я могу просто передать имя метода или мне нужно сначала создать делегат? – 2009-04-07 13:10:36

+0

Проверьте изменения. Вы можете использовать делегат MethodInvoker. Только имя метода не будет достаточным. – NileshChauhan

1

Прикрепите к событиям прогресса стороннего компонента и позвоните по телефону ReportProgress на номер BackgroundWorker. Попросите свой UI подключиться к событию BackgroundWorker.ProgressChanged для обновления пользовательского интерфейса.

0

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

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

Использование таймера (Windows.Forms.Timer), который будет проверять, что очередь каждые x времени и в случае появления новых событий может обновить интерфейс.

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

+0

@Vince - возможно, но его единственный способ бросить события в главном потоке, если у вас нет доступа к «Control» класс и не хотите создавать манекен для простоты событий –

0

Аналогичное обсуждение на this Q. Если вы не можете или не хотите использовать BackgroundWorker по какой-либо причине, вы можете использовать свой собственный поток и события маршала от него обратно в свой поток пользовательского интерфейса.

private void Initialise() {  
    MyLibClass myLibClass = new MyLibClass(); 
    myLibClass.SomeEvent += SomeEventHandler; 
    ThreadPool.QueueUserWorkItem(myLibClass.StartLongTask); 
} 


private void SomeEventHandler(EventArgs e) {  
    if (this.Dispatcher.Thread != Thread.CurrentThread) { 
     this.Dispatcher.Invoke(delegate { DoStuffOnUIThread(e); }); 
    } 
    else {   
     DoStuffOnUIThread(e);  
    } 
} 
Смежные вопросы