Winforms UI Update from Background Stream

This is probably a stupid question, but I could not find an answer to stackoverflow.

I have a button click event in a Winform application that triggers a thread to omit the result for display on the form.

How to update the forms user interface when the stream has calculated the result?

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"); } } 

thanks

+4
source share
4 answers

The easiest way to complete a background task in WinForms is to use BackgroundWorker .

  • Leave it on the form.
  • Connect events. At a minimum, use DoWork . You probably also want RunWorkerCompleted .
  • Record background tasks in the DoWork event.
  • Record any user interface changes in the RunWorkerCompleted event.
  • Call backgroundWorker1.RunWorkerAsync(); to start the process, possibly from some button handler.

Using BackgroundWorker avoids all annoying processing threads and IsInvokeRequired.

Here is a more detailed article.

+13
source

Try using BeginInvoke with a callback function ... this will call your call to another thread and call the method of your choice when the thread finishes:

 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(); } 
+2
source

A very obscure question, I will assume:

  • You are running the Windows Winforms application, not the ASP.Net web page.
  • You want to run a background calculation, which can take a lot of time, and you don't want your user interface to be locked when this happens.
  • You want your user interface to get some sort of result when doing background calculation.
  • You want your background calculation to complete when it provides your user interface with the result.

If so, you should use an asynchronous delegate, not a thread. For instance:

 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(); } 
+2
source

You can either 1. do a theThread.Join() , which blocks the calling thread. 2. Skip the first stream to the second so that it can transfer the call to the main stream that Invoke() should have done so that it can redraw the form.

I am curious. Are you using Asp.Net (WebForms) or WinForms? If you are trying to do this on the Internet, you will need a completely different approach.

0
source

Source: https://habr.com/ru/post/1286101/


All Articles