I am trying to understand how to update a UI from an event while using async/await pattern. Below is the test code I am using on a WinForm app. I am not even sure this is th
Here is another example
async void DoExport()
{
var rMsg = "";
var t = await Task<bool>.Factory.StartNew(() => ExportAsMonthReport(LastMonth.Name, LastYear.Name, out rMsg));
if (t)
{
BeginInvoke((Action)(() =>
{
spinnerMain.Visible = false;
menuItemMonth.Enabled = true;
MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Information, 200);
}));
}
else
{
BeginInvoke((Action)(() =>
{
spinnerMain.Visible = false;
menuItemMonth.Enabled = true;
MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Error, 200);
}));
}
}
You should use Invoke
method of Control
. It executes some code in Control's thread. Also you can check InvokeRequired
property to check if you need to call Invoke
method (it checks if the caller is on a different thread than the one the control was created on).
Simple example:
void SomeAsyncMethod()
{
// Do some work
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)(() =>
{
DoUpdateUI();
}
));
}
else
{
DoUpdateUI();
}
}
void DoUpdateUI()
{
// Your UI update code here
}
In some cases you should check the IsHandleCreated
property of Control
before calling Invoke
method. If IsHandleCreated
returns false then you need wait while Control's handle will be created
The async pattern has support for progress updates.
In short, your async
method can take an IProgress<T>
, and your calling code passes in an implementation of that interface (usually Progress<T>
).
public class ProcessWithUpdates
{
public async Task Run(IProgress<string> progress)
{
await Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
if (progress != null)
progress.Report(String.Format("Update {0}", i));
Thread.Sleep(500);
}
});
}
}
// calling code
ProcessWithUpdates pwp = new ProcessWithUpdates();
await pwp.Run(new Progress<string>(pwp_StatusUpdate));
//Just declare a delegate like so
delegate void Add(string msg);
//Then declare the delegate method like so:
var add = new Add((msg) => {
_listBox_Output.Items.Add(msg);
});
//Now just call the delegate:
void pwe_StatusUpdate(string updateMsg)
{
_listBox_Output.Invoke(add,updateMsg);
}