Reputation: 27618
I'm not sure if I'm doing this correctly, but I have the following code that I am using (click button1, do the _DoWork). The question is this: how do I call the UI to get the values of textbox1 and textbox2 as they cannot be called as they are on a different thread. Should I be using dispatchers?
private void button1_Click(object sender, RoutedEventArgs e)
{
if (textBox1.Text == "")
{
MessageBox.Show("Please enter a username and password", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
else
{
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync();
}
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("asd");
UserManagement um = new UserManagement(sm.GetServerConnectionString());
if (um.AuthUser(textBox1.Text, textBox2.Password))
{
MainWindow mw = new MainWindow();
mw.Show();
this.Close();
}
else
{
if (um.Timeout)
{
MessageBox.Show("Could not connect to server, please check your configuration", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
MessageBox.Show("Incorrect username or password", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
Should I be using background worker?
Upvotes: 8
Views: 19565
Reputation: 18000
You cannot access UI elements directly from a BackgroundWorker.To do so you have to use Dispatcher. WPF objects which derive from DependencyObject have thread affinity which means that only the thread that instantiates them can access their members.
Check the link below and see if the code sample helps you
http://social.msdn.microsoft.com/Forums/en/wpf/thread/4858bcaf-1cb2-410b-989a-18b874ffa458
Upvotes: 0
Reputation: 3268
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.
}
}
Upvotes: 13
Reputation: 35477
As the name implies, the Background Worker does not run on the UI thread. You can only access UI controls when on the UI thread. An easy way to work around this issue, is to save the text box properties you need in a need a new "object" and then pass it to RunWorkerAsync. This object is available to your DoWork method in e.Argument.
However, you also have an issue with showing a form on a worker thread.
Upvotes: 3