WPF multithreaded progress dialog

心已入冬 提交于 2019-12-01 00:28:02

You need to read from the TextBoxes (txtEmail and txtPwd) on the foreground thread, not the background thread. Here's an example:

class MainWindow
{
  private string _email;
  private string _password;

  private void btnLogin_Click(...)
  {
    // running on UI thread here - can touch text boxes
    _email = txtEmail.Text;
    _password = txtPwd.Text;
    // ... set up worker ...
    worker.RunWorkerAsync();
  }

  private void login()
  {
    binding = new Service();
    // running on background thread here
    // but safe to access _email and _password they're just data, not UI controls
    lr = binding.login(_email, _password);
  }
}

EDIT: Even better, pass the email and password as arguments rather than storing them in member variables:

  private void btnLogin_Click(...)
  {
    // running on UI thread here - can touch text boxes
    LoginInfo loginInfo = new LoginInfo(txtEmail.Text, txtPwd.Text);
    // ... set up worker ...
    worker.RunWorkerAsync(loginInfo);  // note argument
  }

  private void worker_DoWork(...)
  {
    LoginInfo loginInfo = (LoginInfo)(e.Argument);
    // now pass the LoginInfo to login() as an argument
  }

(and remove the _email and _password members)

You're thinking about this the wrong way.

You need to show your progress dialog on your main thread, no in your background worker.

Then, in the BackgroundWorker.DoWork handler, you do your actual work. This runs in the background thread.

On regular intervals, while your work is progressing, call BackgroundWorker.ReportProgress. This will push the progress into an even on the UI thread.

You'll want to subscribe to the BW.ProgressChanged event, and here is where you'll update the progress bar in your progressDialog. This happens on the UI thread automatically.

Your work, and the calls to ReportProgress, need to be the only things in the DoWork event handler.

To access UI elements in event handlers called from events raised in a non-UI thread you need something like the following code:

Action action = () => FinalUpdate();
if (Thread.CurrentThread != Dispatcher.Thread)
{
    Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, action);
}
else
{
    action();
}

If you can, get hold of a copy of More Effective C# by Bill Wagner. He has a whole section on multithreading and the background worker thread.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!