Reputation: 25
I'm working on a Splash/Loading screen for an app and I'd like to have a progress bar as well as a label on it which will notify the user of current process, e.g. connecting to the database, loading user settings, retrieving x data, retrieving y data.
I only did a tiny bit of BackGroundWorker stuff in VB before and nothing in C# so a bit confused where to start as it looks quite different in C#.
I'd like to keep the form class simple as to only calling specific methods from different classes on a different thread.
I mainly need to know how to update the GUI from the class that does the work as I think I could work out the threading itself from the below code:
using System;
using System.Threading;
public class ThreadWork
{
public static void DoWork()
{
for(int i = 0; i<3;i++) {
Console.WriteLine("Working thread...");
Thread.Sleep(100);
}
}
}
class ThreadTest
{
public static void Main()
{
Thread thread1 = new Thread(ThreadWork.DoWork);
thread1.Start();
for (int i = 0; i<3; i++) {
Console.WriteLine("In main.");
Thread.Sleep(100);
}
}
}
Upvotes: 0
Views: 75
Reputation: 43553
You could use the Task.Run
method to offload work to a ThreadPool
thread, and a Progress<string>
object to report progress from the background thread to the UI. You can also use async/await in order to write your code in a straightforward way. Here is an example:
private async void Form_Load(object sender, EventArgs e)
{
IProgress<string> progress = new Progress<string>(message =>
{
Label1.Text = message;
});
var result = await Task.Run(() =>
{
progress.Report("Connecting to database...");
ConnectToDatabase();
progress.Report("Loading user settings...");
LoadUserSettings();
progress.Report("Retrieving x data...");
return RetrieveXData();
});
// At this point the background processing has completed
Label1.Text = $"Done! ({result})";
}
If you have heterogeneous data to report at different intervals, you can use multiple Progress<T>
objects (for example a Progress<string>
, a Progress<int>
etc). You can also use a complex type for reporting, for example Progress<(string, int)>
.
Upvotes: 2
Reputation: 279
Although Mitch's answer will work. You can also use TaskSchedulers to handle background work and then respond back to UI:
public static void Main()
{
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => DoBackgroundWork(uiScheduler));
}
private static void DoBackgroundWork(TaskScheduler uiScheduler)
{
// Do background stuff here...
Task.Factory.StartNew(() =>
{
// Respond back to UI here
Console.WriteLine("Doing work");
// Or if you have to change GUI, let's say a label value;
label1.Text = "Text changed by background Task";
}, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
// Some other background work
}
Upvotes: 1