簡體   English   中英

線程凍結主UI

[英]Thread freezes main UI

你好
我正在編寫服務器監控應用程序。

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

我目前有一個Page wihtin我的主窗口,我在那里Exucute並填充數據:
方法

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等待Thread完成,似乎無法弄清楚為什么會發生這種情況。

所有幫助贊賞!

問題是Dispatcher.Invoke阻塞了UI線程,因此任何Invoke都應該盡可能小。

將耗時的代碼放在調用之外以解決問題。

正如@RohitVals所指出的那樣,你無法從后台線程訪問UI控件,所以你必須使用2個調用 - 一個用於獲取文本值,一個用於設置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)

您可以在運行線程之前獲取這些值以避免雙重調度:

text = textbox_Username.Text;
// ...

Thread test = ...

要么

您可能想嘗試MVVM模式 - http://msdn.microsoft.com/en-us/magazine/dd419663.aspx 它可能看起來令人生畏,而且過於復雜,一開始沒有或沒有什么優勢,但你會看到它的優點隨着時間的推移。

這篇特別的文章涉及MVVM和Dispathcer - http://msdn.microsoft.com/en-us/magazine/dn630646.aspx

PS:如果你的GetDisksInfo方法使用延遲執行(如LINQ),那么你應該在使用它之前枚舉結果:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM