简体   繁体   中英

Background worker proper way to access UI

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?

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.
     }
  }

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.

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

this.Dispather.Invoke((Action)delegate(){
    this.Close();
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM