2009-06-11 4 views
4

Это, наверное, глупый вопрос, но я не смог найти ответ на stackoverflow.Обновление Winforms UI из фонового потока результата

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

Как обновить пользовательский интерфейс форм, когда поток рассчитал результат?

private void btnRequestR2Approval_Click(object sender, EventArgs e) 
    { 
     if (User.IsLogged) 
     { 
      ValidationResults results = new ValidationResults(); 
      results.Show(); 

      Logger log = Logger.Instance(); 
      Logger.NewLogAddedHandler messageDelegate = new Logger.NewLogAddedHandler(results.NewLogMessage); 

      if (!log.IsEventHandlerRegistered()) 
      { 
       log.NewLogAdded += messageDelegate; 
      } 

      ThreadStart operation = new ThreadStart(ValidateAndSubmit); 
      Thread theThread = new Thread(operation); 
      theThread.Start(); 

     } 
     else 
     { 
      MessageBox.Show("Please login"); 
     } 

    } 

Спасибо

+0

Вы спрашиваете об ASP.NET (веб-технологии) или Winforms (родная технология Windows)? Вопрос выглядит так, как будто вы используете WinForms, но заголовок и теги указывают на другое. – jrcs3

+1

Что означает «законченный запуск»? Что поток вышел, или что поток вычислил то, что вам нужно знать? –

+0

закончил работать, означает, что поток вычислил что-то, и мне нужно что-то обновить в другом потоке – Sergey

ответ

13

Самый простой способ выполнения фоновой задачи в WinForms - использовать BackgroundWorker.

  • Оставьте заявку на форму.
  • Провести мероприятия. Как минимум, используйте DoWork. Вероятно, вы также захотите RunWorkerCompleted.
  • Запишите фоновые задачи в событии DoWork.
  • Запишите любые изменения пользовательского интерфейса в событии RunWorkerCompleted.
  • Звоните backgroundWorker1.RunWorkerAsync();, чтобы начать процесс, возможно, с помощью какого-либо обработчика кнопок.

Использование BackgroundWorker позволяет избежать всех раздражающих потоков обработки и IsInvokeRequired stuff.

Подробнее ... how-to article.

0

Вы можете 1. сделать theThread.Join(), который будет блокировать вызывающий поток. 2. Пропустите первый поток до второго, чтобы он мог выполнить обратный вызов в основной поток, который должен был бы сделать Invoke(), чтобы он мог перерисовать форму.

Мне все же интересно. Вы используете Asp.Net (WebForms) или WinForms? Если вы пытаетесь сделать это в Интернете, вам понадобится совершенно другой подход.

+0

Win Forms, и я попытался использовать theThread.Join(), он блокирует все приложение. – Sergey

+0

Это потому, что Thread.Join будет ждать завершения потока, что именно вы просили. Если это не то, что вы имеете в виду, пожалуйста, обновите свой вопрос. –

2

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

private void btnRequestR2Approval_Click(object sender, EventArgs e) 
{ 
    if (User.IsLogged) 
    { 
     ValidationResults results = new ValidationResults(); 
     results.Show(); 

     Logger log = Logger.Instance(); 
     Logger.NewLogAddedHandler messageDelegate = new Logger.NewLogAddedHandler(results.NewLogMessage); 

     if (!log.IsEventHandlerRegistered()) 
     { 

      log.NewLogAdded += messageDelegate; 
     } 

     ThreadStart operation = new ThreadStart(ValidateAndSubmit); 
     operation.BeginInvoke(MyCallBack, this); 
    } 
    else 
    { 
     MessageBox.Show("Please login"); 
    } 

} 

private static void MyCallBack(IAsyncResult ar) { 
    ((MyForm)ar.AsyncState).Refresh(); 
} 
+0

Вы должны вызвать ar.EndInvoke или MyCallback будет утечка ресурсов машины. –

+0

нет такого метода в ar ,,, было бы все еще так? – Sergey

+0

Это на самом деле (AsyncDelegate) ar.EndInvoke, см. Мой ответ. –

2

Очень неясный вопрос, я буду считать, :

  1. У вас работает приложение Windows Winforms, а не веб-страница ASP.Net.
  2. Вы хотите вызвать расчет фона, который может занять много времени, и не хотите, чтобы ваш пользовательский интерфейс блокировался, когда это происходит.
  3. Вы хотите, чтобы ваш пользовательский интерфейс получил какой-то результат при выполнении фонового расчета.
  4. Вы хотите, чтобы ваш фоновый расчет завершился, когда он предоставил ваш пользовательский интерфейс с результатом.

Если это правда, вы должны использовать асинхронный делегат, а не поток. Например:

string SleepAndReturnParam(string param1) 
{ 
    System.Threading.Thread.Sleep(10000); 
    return param1; 
} 

// Declare a delegate matching our async method. 
public delegate string DelegateWithParamReturningString(string param1); 


private void button1_Click(object sender, EventArgs e) 
{ 
    var myDelegate = new DelegateWithParamReturningString(SleepAndReturnParam); 

    // Run delegate in thread pool. 
    myDelegate.BeginInvoke("param1", 
     OnCallBack, // Completion callback 
     this); // value to pass to callback as AsyncState 
} 


private void OnCallBack(IAsyncResult ar) 
{ 
    // first cast IAsyncResult to an AsyncResult object 
    var result = ar as System.Runtime.Remoting.Messaging.AsyncResult; 

    // grab the delegate 
    var myDelegate = result.AsyncDelegate as DelegateWithParamReturningString; 

    // Exit delegate and retrieve return value. 
    string returnValue = myDelegate.EndInvoke(ar); 

    // Declare an anonymous method to avoid having to define 
    // a method just to update a field. 
    MethodInvoker formFieldUpdater = delegate 
    { 
     formTextField.Text = returnValue; 
    }; 

    // Winforms controls must be modified on the thread 
    // they were created in. 
    if (formTextField.InvokeRequired) 
     Invoke(formFieldUpdater); 
    else 
     formFieldUpdater(); 
} 
Смежные вопросы