WPF文本框内容在加载时冻结UI

时间:2018-11-22 13:27:02

标签: c# wpf user-interface textbox

我开始编写我的第一个WPF应用程序的代码,但是在显示一些系统信息(cpu,内存,磁盘使用情况,mac地址等)的文本框时遇到了问题。 我的应用程序在两个页面之间导航,并且所述文本框在页面之一上。通过WMI查询检索文本框的内容。 我注意到的问题是,在导航到带有文本框的tha页面时,它将冻结UI大约两秒钟,然后再进入并显示该页面。 我是新手,我最好的猜测是,有八个WMI查询(也可能编码不正确)正在执行此操作,或者我在文本框中错误地加载了内容。 有关如何构造查询的示例

public string getCPU()
    {
        ManagementObjectSearcher searcher = new
        ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_Processor");
        StringBuilder sb = new StringBuilder();
        foreach (ManagementObject wmi in searcher.Get())
        {
            try
            {
                sb.Append("Processor: " + wmi.GetPropertyValue("Name").ToString() + Environment.NewLine);
            }
            catch
            {
                return sb.ToString();
            }
        }
        return sb.ToString();
    }
    public string getRAMsize()
    {
        ManagementClass mc = new ManagementClass("Win32_ComputerSystem");
        ManagementObjectCollection moc = mc.GetInstances();
        foreach (ManagementObject item in moc)
        {
            return Convert.ToString(Math.Round(Convert.ToDouble(item.Properties["TotalPhysicalMemory"].Value) / (1024 * 1024 * 1024), 0)) + " GB";
        }

        return "RAMsize";
    }

这就是我用来检索文本框中数据的方法:

private void TextBox1_Loaded(object sender, RoutedEventArgs e)
    {
        TextBox1.Text = getCPU();
        TextBox1.Text += "Memory:  " + getRAMsize() + Environment.NewLine;
        TextBox1.Text += "Free Space:  " + GetTotalFreeSpace(sysdrive) + " GB" + Environment.NewLine;
        if (Is64BitSystem)
        {
            TextBox1.Text += getOS() + " 64bit" + Environment.NewLine;
        }
        else
        {
            TextBox1.Text += getOS() + " 32 Bit" + Environment.NewLine;
        }
        TextBox1.Text += "MAC Address : " + System.Text.RegularExpressions.Regex.Replace(GetMacAddress().ToString(), ".{2}", "$0 ") + Environment.NewLine;
        TextBox1.Text += av();
    }

我的问题是我在做错什么,我该如何解决。在我看来,如果查询构造正确,那是因为每次在加载文本框时(在导航或启动时)一次又一次地执行查询,也许如果我可以让它仅加载一次并记住这些值(因为大多数数据应保持不变)。 但是正如我所说,我是菜鸟,任何帮助将不胜感激。 预先感谢

2 个答案:

答案 0 :(得分:0)

检查完每个查询后,我发现getCPU导致加载延迟。 我将其替换为Registry.GetValue,这非常快。 感谢Sebastian L,因为尽管他的代码虽然对我不起作用,但它使我走上了正确的道路,而且我能够与背景工作人员一起修改自己的代码,从而避免了任何形式的UI冻结 我的工作代码:

private void TextBox1_Loaded(object sender, RoutedEventArgs e)
    {

        BackgroundWorker bw = new BackgroundWorker();
        bw.WorkerReportsProgress = true;
        bw.DoWork += new DoWorkEventHandler(delegate (object o, DoWorkEventArgs args)
        {

        });
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate (object o, RunWorkerCompletedEventArgs args)
        {
            TextBox1.Text = (string)Registry.GetValue(@"HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0", "ProcessorNameString", null) + Environment.NewLine;
            TextBox1.Text += "Memory:  " + getRAMsize() + Environment.NewLine;
            TextBox1.Text += "Free Space:  " + GetTotalFreeSpace(sysdrive) + " GB" + Environment.NewLine;
            if (Is64BitSystem)
            {
                TextBox1.Text += getOS() + " 64bit" + Environment.NewLine;
            }
            else
            {
                TextBox1.Text += getOS() + " 32 Bit" + Environment.NewLine;
            }
            TextBox1.Text += "MAC Address : " + System.Text.RegularExpressions.Regex.Replace(GetMacAddress().ToString(), ".{2}", "$0 ") + Environment.NewLine;
            TextBox1.Text += av();
        });
        bw.RunWorkerAsync();
    }

答案 1 :(得分:-1)

您正在UI线程中获取数据。

您应该将数据加载到后台线程中,然后由于使用wpf,因此将文本框文本绑定到变量。

示例(此代码可复制粘贴):

// INotifyPropertyChanged is an Interface which enables binding of Properties in your window
public partial class MainWindow : Window, INotifyPropertyChanged
{
    private string _systemInformation;

    // Stub (works actually)
    private bool is64BitSystem = (IntPtr.Size == 8);

    // Stub
    private string sysdrive = "YOLO\\:";

    public MainWindow()
    {
        InitializeComponent();
        // Set Datacontext normally set to a viewmodel but ther is none in this code
        this.DataContext = this;

        // The Backgroundworker does things in the background (nonblocking)
        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += DoItButDontInterruptMeDuh;
        bw.RunWorkerAsync();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public string SystemInformation { get => _systemInformation; set => _systemInformation = value; }

    //Stub
    public string getCPU()
    {
        return "Fancy CPU";
    }

    //Stub
    public string getRAMsize()
    {
        return "1 PB";
    }

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    //Stub
    private string av()
    {
        return "Whatever av means.";
    }

    private void DoItButDontInterruptMeDuh(object sender, DoWorkEventArgs e)
    {
        // Simulate loading time
        Thread.Sleep(5000);

        SystemInformation = getCPU();
        SystemInformation += "Memory:  " + getRAMsize() + Environment.NewLine;
        SystemInformation += "Free Space:  " + GetTotalFreeSpace(sysdrive) + " GB" + Environment.NewLine;
        if (is64BitSystem)
        {
            SystemInformation += getOS() + " 64bit" + Environment.NewLine;
        }
        else
        {
            SystemInformation += getOS() + " 32 Bit" + Environment.NewLine;
        }
        SystemInformation += "MAC Address : " + System.Text.RegularExpressions.Regex.Replace(GetMacAddress().ToString(), ".{2}", "$0 ") + Environment.NewLine;
        SystemInformation += av();
        OnPropertyChanged("SystemInformation");
    }

    //Stub
    private object GetMacAddress()
    {
        return "Macintoshstreet 1234";
    }

    //Stub
    private string getOS()
    {
        return "Cool OS";
    }

    //Stub
    private string GetTotalFreeSpace(object sysdrive)
    {
        return "0";
    }
}

以及.xaml:

<TextBox Text={Binding Path=SystemInformation}/>