螺纹冻结主UI螺纹、UI

2023-09-04 03:37:01 作者:6.安意

您好林目前正在写一个服务器监控应用。 类

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

我现在有一个页面wihtin我的主窗口,我Exucute和填充数据: 方法

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.");
  }

问题

我mainThread等待线程完成,似乎无法弄清楚为什么会这样。

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

所有帮助AP preciated!

All help appreciated!

推荐答案

的问题是, Dispatcher.Invoke 阻塞UI线程,因此任何调用应尽可能的小。

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

把你的耗时code中的调用之外来解决这个问题。

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

和,因为它已经指出通过@RohitVals您无法访问从后台线程的UI控件,所以你将不得不使用2调用 - 一个拿到文本值,一个集的ItemsSource

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();

或(感谢@RohitVals)

您可以运行的线程,以避免双重派遣之前获取这些值:

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

text = textbox_Username.Text;
// ...

Thread test = ...

您可能想尝试MVVM模式 - http://msdn.microsoft .COM / EN-US /杂志/ dd419663.aspx 。它可能看起来令人生畏并没有或几乎没有优势,一开始太复杂,但你会看到随着时间的推移它的优点。

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.

这条特别处理MVVM和Dispathcer - http://msdn.microsoft .COM / EN-US /杂志/ dn630646.aspx

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

PS:如果你的 GetDisksInfo 方法使用延迟执行(如LINQ),那么你应该使用它之前列举的结果:

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();