содержимое текстового поля wpf замораживает пользовательский интерфейс при загрузке - PullRequest
0 голосов
/ 22 ноября 2018

Я начал кодировать свое первое приложение WPF, и у меня возникли проблемы с текстовым полем, в котором отображается некоторая системная информация (процессор, память, использование диска, MAC-адрес и т. Д.).Мои приложения имеют навигацию между двумя страницами, и указанное текстовое поле находится на одной из страниц.Содержимое текстового поля извлекается с помощью запросов WMI.Проблема, которую я заметил, заключается в том, что при переходе на страницу с текстовым полем пользователь останавливает интерфейс на две секунды перед тем, как перейти на страницу и отобразить ее.Я новичок, и я думаю, что многие запросы 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 голосов
/ 24 ноября 2018

После проверки каждого запроса я обнаружил, что getCPU вызывает задержку загрузки.Я заменил его Registry.GetValue, который работает очень быстро.Благодаря Себастьяну Л., потому что его код не работал для меня, он поставил меня на правильный путь, и я смог адаптировать собственный код с помощью фонового работника, чтобы избежать зависания пользовательского интерфейса в любом виде моего рабочего кода:

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();
    }
0 голосов
/ 22 ноября 2018

Вы запрашиваете ваши данные в потоке пользовательского интерфейса.

Вы должны загрузить данные в фоновом потоке, а затем, поскольку вы используете 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}/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...