Thread freezes main UI

本秂侑毒 提交于 2019-12-07 20:14:50

问题


Hello
Im currently writing a Server monitoring application.
Classes

    public class Server
    {
            public string SERVERNAME;
            public string ENVIRONMENT;
            public string VERSION;

            public string CPU_PERCETAGE;
            public string CPU_NAME;
            public string CPU_DESCRIPTION;
            public string CPU_VOLTAGE;
    }

I currently have a Page wihtin my mainwindow where I Exucute and fill the data:
Method

try
 {
   {
    Thread test = new Thread(() =>
    {
     datagrid_Disks.Dispatcher.BeginInvoke(
      new Action(() =>
      {
        datagrid_Disks.ItemsSource = Server.GetDisksInfo(textbox_Username.Text,
                                                           textbox_password.Password,
                                                           textbox_IP.Text,
                                                           textbox_Domain.Text);
      }));
     });
     test.Start();
  }
  catch (UnauthorizedAccessException)
  {
    Worker.ShowModernBox("Onjuiste gebruiksersnaam" + Environment.NewLine + "of wachtwoord.");
  }
  catch (ManagementException)
  {
   Worker.ShowModernBox("Server geeft geen Response." + Environment.NewLine + "Controleer Aub de instelling.");
  }

Problem

My mainThread waits for the Thread to finish, cannot seem to figure why this happens.

All help appreciated!


回答1:


The problem is that the Dispatcher.Invoke blocks the UI thread, so any Invoke should be as small as possible.

Put your time-consuming code outside the invoke to solve the issue.

And as it has been pointed by @RohitVals you can't access the UI control from background thread, so you will have to use 2 invokes - one to get text values, one to set ItemsSource :

Thread test = new Thread(() =>
{
    String text, password, ipText, domainText;

    // !!!!!!This one should be simple Invoke because otherwise variables may not get their         
    // values before calls. Thanks @ScottChamberlain.!!!!!!
    datagrid_Disks.Dispatcher.Invoke(
      new Action(() =>
      {
          text = textbox_Username.Text;
          password = textbox_password.Password;
          ipText = textbox_IP.Text,
          domainText = textbox_Domain.Text
      }));


     var result = Server.GetDisksInfo(text, 
         password, 
         ipText,
         domainText);

     datagrid_Disks.Dispatcher.BeginInvoke(
      new Action(() =>
      {
        datagrid_Disks.ItemsSource = result;
      }));
 });

 test.Start();

OR (thanks to @RohitVals)

You can get these values before running the thread to avoid the double dispatch:

text = textbox_Username.Text;
// ...

Thread test = ...

OR

You may want to try the MVVM pattern - http://msdn.microsoft.com/en-us/magazine/dd419663.aspx. It may look intimidating and far too complex for no or little advantages at the beginning, but you will see its merits with time.

This particular article deals with MVVM and Dispathcer - http://msdn.microsoft.com/en-us/magazine/dn630646.aspx

P.S.: If your GetDisksInfo method uses deferred execution (like LINQ) then you should enumerate the result before using it:

 var result = Server.GetDisksInfo(text, 
         password, 
         ipText,
         domainText).ToArray();


来源:https://stackoverflow.com/questions/25219860/thread-freezes-main-ui

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