Accessing UI Control from Backgroundworker Thread

Accessing UI Control from BackgroundWorker Thread

Here's a snippet which I find very handy:

public static void ThreadSafe(Action action)
{
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal,
new MethodInvoker(action));
}

You can pass it any delegate of Action type or simply a lambda like this:

ThreadSafe(() =>
{
[your code here]
});

or

ThreadSafe(listBoxServers.Items.Clear);

Background worker proper way to access UI

You can pass data into the worker via the argument of the RunWorkerAsync call and pass data out via DoWorkEventArgs.Result...

  class AuthUserData
{
public string Name;
public string Password;
}

private void button1_Click(object sender, EventArgs e)
{
var authData = new AuthUserData() { Name = textBox1.Text, Password = textBox2.Text };
worker.RunWorkerAsync(authData);
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
// On the worker thread...cannot make UI calls from here.
var authData = (AuthUserData)e.Argument;
UserManagement um = new UserManagement(sm.GetServerConnectionString());
e.Result = um;
e.Cancel = um.AuthUser(textBox1.Text, textBox2.Password));
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Back on the UI thread....UI calls are cool again.
var result = (UserManagement)e.Result;
if (e.Cancelled)
{
// Do stuff if UserManagement.AuthUser succeeded.
}
else
{
// Do stuff if UserManagement.AuthUser failed.
}
}

How to directly access the UI thread from the BackgroundWorker thread in WPF?

Have you looked at using Dispatcher.Invoke?

Dispatcher.Invoke(new Action(() => { Button_Start.Content = i.ToString(); }));

Or use BeginInvoke if you want something to happen asynchronously.

Can I update UI from BackgroundWorker.RunWorkerCompleted

Your code doesn't have a UI thread. Since you don't have a UI thread, and didn't call RunWorkerAsync from a UI thread (which is required for it to know what UI thread to marshall the event handlers to) it can't call any of the event handlers in a (non-existent) UI thread.

Create a UI application (a winforms or WPF application, for example), make sure to create and run the BGW from a UI thread, and then you'll see that you can manipulate the controls from the various events (other than DoWork, obviously).

Access windows control from Backgroundworker DoWork

You can only access Windows Forms controls from the GUI thread. If you want to manipulate them from another thread, you will need to use the Control.Invoke method to pass in a delegate to execute on the GUI thread. In your situation, you should be able to do this:

private void bgwBackground_DoWork(object sender, DoWorkEventArgs e)
{
foreach (Control controlOut in LayoutPanel1.Controls)
{
this.Invoke(new MethodInvoker(delegate {
// Execute the following code on the GUI thread.
string myString = controlOut.Name;
}));
}
}

I like to define an extension method that allows me to use the cleaner lambda syntax:

// Extension method.
internal static void Invoke(this Control control, Action action) {
control.Invoke(action);
}

// Code elsewhere.
this.Invoke(() => {
string myString = controlOut.Name;
});

C# - How do you access information in form controls from a backgroundworker thread

The elegant way of doing this is to create a list of only the data (such as directories) you are interested in and pass it to the BackgroundWorker's DoWorkEventArgs.

You should never pass Forms controls to a BackgroundWorker; doing that can cause cross-thread exceptions, crash your UI, and cause race conditions as both the UI and worker try to use the same data. Only pass the data you actually need to another thread.



Related Topics



Leave a reply



Submit