I always recommend developers to avoid Invoke
/BeginInvoke
/RunAsync
, because it encourages a poor design: your backend/business logic types end up driving the UI (and taking a dependency on a specific UI framework).
A better approach is to either use IProgress<T>
/Progress<T>
(if your UI updates are progress updates) or IObservable<T>
(if your backend is asynchronously producing a series of values).
Adding items to a list sounds to me more like an asynchronous series, but since you specifically asked about IProgress<T>
I'll show an example of that:
private static async Task DoSomethingAsync()
{
Progress<object> progress = new Progress<object>(item => F.ls1.Items.Add(item));
await Task.Run(() => BackgroundWork(progress));
}
private static void BackgroundWork(IProgress<object> progress)
{
// Do background work here.
var item = "NewItem";
// Notify UI of progress.
if (progress != null)
progress.Report(item);
}
If you wanted to use IObservable<T>
, then your code could look something like this:
private static void StartSomething()
{
IObservable<object> items = BackgroundWork();
items.ObserveOn(F).Subscribe(item => F.ls1.Items.Add(item), ex => HandleException(ex));
}
Note that with both of these approaches, the code doing the background work does not care what context it executes in. It just produces a series of progress updates or a series of values. The UI layer then consumes those progress reports/values and updates the UI accordingly.