引发异常:WindowsBase.dll中的"System.InvalidOperationException" [英] Exception thrown: 'System.InvalidOperationException' in WindowsBase.dll

查看:46
本文介绍了引发异常:WindowsBase.dll中的"System.InvalidOperationException"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法在WPF UI中进行某些更新.引发异常的代码的同一部分在其他函数中也可以正常工作.现在,由于某种原因,我不知道它不仅引发了异常,而且也没有像我想要的那样进行更新.我希望 OnCPUDetEvent()函数中的UI元素根据我设置的计时器进行更新.

I'm having trouble having something update in my WPF UI. The same part of the code that's throwing the exception works just fine in the other function. Now, for some reason, I can't figure out it's not only throwing an exception, it is also not updating like I want it to. I want the UI elements in the OnCPUDetEvent() function to update based off of the timer I have set up.

这是我的代码:

using System;
using System.Collections.Generic;
using System.Management.Instrumentation;
using System.Management;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Runtime.Serialization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace HWDetCS
{
    /// <summary>
    /// Interaction logic for CPUBase.xaml
    /// </summary>
    public partial class CPUBase : Page
    {

        // lists are better than arrays, fite me!
        public List<string> names = new List<string>();
        public List<string> values = new List<string>();
        public int i = 0;

        // Set up a timer to be enabled later
        public Timer CPUDetRefreshTimer;


        public CPUBase()
        {
            // Auto generated stuff, don't touch!
            InitializeComponent();

            // Actually run all the detection stuff
            CPUDet();

            // Start up the Timer, and get it ready
            CPUDetRefreshTimer = new Timer();
            CPUDetRefreshTimer.AutoReset = true;
            CPUDetRefreshTimer.Interval = 500;
            CPUDetRefreshTimer.Enabled = true;
            CPUDetRefreshTimer.Elapsed += OnCPUDetEvent;

        }

        // This thing does all the work
        public void CPUDet()
        {
            // Get the CPU Management class, this makes it the CPU we get info off of rather than nothing, because if it wasnt set to the CPU, it would error and break and cry a lot... dont change it.
            ManagementClass CPUClass = new ManagementClass("Win32_Processor");
            CPUClass.Options.UseAmendedQualifiers = true;

            // Set up a data collection to get the data off of, this and the next thing SHOULD NEVER BE IN A LOOP! IT WILL BREAK YOUR CPU LIKE A BALLOON!
            PropertyDataCollection dataCollection = CPUClass.Properties;

            // Get the instance of the class, for some reason this is required to work, dont touch AND DONT PUT IT IN A LOOP WHY CANT YOU LISTEN!?
            ManagementObjectCollection instanceCollection = CPUClass.GetInstances();



            // This is a loop, its very fragile, dont touch it, it gets the list of data we are collecting
            foreach (PropertyData property in dataCollection)
            {

                // adds the names into one nice readable-ish list!
                names.Add(property.Name);

                // loop through all the instances and grabs the actual data off of it
                foreach (ManagementObject instance in instanceCollection)
                {
                    // makes sure we dont get null reference errors, I HATE THOSE SO MUCH! I KNOW ITS NULL JUST SHUT UP!
                    if (instance.Properties[property.Name.ToString()].Value == null)
                    {
                        // if its null, dont add the actual property data, INSTEAD, add a string that says null so we know not to mess with it
                        values.Add("null");
                    }
                    else
                    {
                        // otherwise, go right ahead
                        values.Add(instance.Properties[property.Name.ToString()].Value.ToString());
                    }
                }
                // counting....
                i++;

            }



            // Debug stuff, dont release uncommented!
            // TODO: COMMENT THIS OUT!
            for (int x = 0; x < names.Count - 1; x++)
            {
                Console.WriteLine(x.ToString());
                Console.WriteLine(names[x]);
                Console.WriteLine(values[x]);
            }

            // Get the name
            CPUNameText.Content = values[29];
            // Get the manufacturer
            CPUManuText.Content = values[27];
            // Get the number of CORES (NOT THREADS!)
            CPUCoreCountText.Content = values[30];
            // Get the Family
            CPUFamilyText.Content = values[18];

        }

        public void OnCPUDetEvent(Object obj, ElapsedEventArgs args)
        {
            //Console.WriteLine("Event Fire!");

            // Get the current clock speed
            CPUClockSpeedText.Content = values[10] + "MHz";
            // Get the current Voltage
            CPUCVoltageText.Content = (Convert.ToDouble(values[11]) / 10).ToString() + " Volts";
        }
    }


}

这是实际UI页面的XAML:

Here is the XAML for the actual UI Page:

<Page x:Class="HWDetCS.CPUBase"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:HWDetCS"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="CPUBase" MinWidth="1280" MinHeight="720">

    <Grid Background="Gray">
        <DockPanel>
            <UniformGrid Rows="6" Columns="2">
                <Label x:Name="CPUNameLabel" Content="CPU Name:" FontSize="36" FontWeight="Bold" Foreground="#FF007ACC" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
                <Label x:Name="CPUNameText" Content="Label" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="24" FontWeight="Bold" Foreground="#FF007ACC"/>
                <Label x:Name="CPUManuLabel" Content="CPU Manufacturer:" FontSize="36" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontWeight="Bold" Foreground="#FF007ACC"/>
                <Label x:Name="CPUManuText" Content="Label" Foreground="#FF007ACC" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="24" FontWeight="Bold"/>
                <Label x:Name="CPUClockSpeedLabel" Content="CPU Clock Speed:" Foreground="#FF007ACC" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="36" FontWeight="Bold"/>
                <Label x:Name="CPUClockSpeedText" Content="Label" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="24" FontWeight="Bold" Foreground="#FF007ACC"/>
                <Label x:Name="CPUCoreCountLabel" Content="CPU Core Count:" Foreground="#FF007ACC" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="36" FontWeight="Bold"/>
                <Label x:Name="CPUCoreCountText" Content="Label" Foreground="#FF007ACC" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="24" FontWeight="Bold"/>
                <Label x:Name="CPUFamilyLabel" Content="CPU Family:" FontSize="36" FontWeight="Bold" Foreground="#FF007ACC" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
                <Label x:Name="CPUFamilyText" Content="Label" Foreground="#FF007ACC" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="24" FontWeight="Bold"/>
                <Label x:Name="CPUCVoltageLabel" Content="CPU Current Voltage:" FontSize="36" FontWeight="Bold" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Foreground="#FF007ACC"/>
                <Label x:Name="CPUCVoltageText" Content="Label" Foreground="#FF007ACC" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="24" FontWeight="Bold"/>
            </UniformGrid>
        </DockPanel>
    </Grid>
</Page>

推荐答案

您收到的错误是访问被拒绝"错误的结果.您的函数在与GUI本身不同的线程中开始其生命,因此不允许更改GUI元素.

The error you got is the result of an "access denied" error. Your function starts its life in a different thread than the GUI itself, as a result it is not allowed to change GUI elements.

此链接中对此进行了描述:在非UI上运行的方法线程更新用户界面

It is described in this link: A method running on a non-UI thread updates the UI

上面的链接提供了逃避问题的方法.但是,没有单一的解决方案可以解决您的问题.以下只是其中之一.它会逐步进行您需要应用的更改.(我在下一个答案中添加了另一个解决方案)

Above link gives methods to run away from the problem. However, there is no single solution for your problem. The following is just one of them. It does step-by-step changes you need to apply. ( I have added another solution in the next answer)

使用System.ComponentModel; 添加到标题中.这是为了使用具有更改属性的绑定.如果需要,请添加参考dll文件.

Add using System.ComponentModel; to your headers. This is to use binds with changing properties. If needed, add the reference dll file.

现在为您的班级使用此标题:

Now use this heading for your class :

公共局部类CPUBase:Page,INotifyPropertyChanged

下一步是添加通知程序.该代码按原样使用.NET v4.0,请参考 INotifyPropertyChanged界面如何用于其他版本.

Next step is adding notifiers. The code is used as is for .NET v4.0, consult to INotifyPropertyChanged Interface how to use for other versions.

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

现在创建两个属性字段来保存您的更改值.请查阅上面的链接以获取其他版本.

now create two property field to hold your changing values. Consult the above link for other versions.

string speed;
public string Speed
{
    get
    {
        return speed;
    }
    set
    {
        speed= value;
        NotifyPropertyChanged(nameof(Speed));
    }
}
string volt;
public string Volt
{
    get
    {
        return volt;
    }
    set
    {
        volt = value;
        NotifyPropertyChanged(nameof(Volt));
    }
}

剩下的事情现在要容易得多.只需在函数中更改这些属性即可(额外的 i 会显示其正在工作,因为值不会立即显示更改)(加法有效,但我不认为代码会得到有效 ,我尝试降低CPU频率,结果没有变化)

The rest is much easier now. just change these properties inside your function (extra i is to show it is working as the values don't show immediate changes) ( Additions work but I don't think the code gets active values, I tried to decrease CPU freq, and result didnt change)

Speed = values[10] + "MHz"+i;
Volt = (Convert.ToDouble(values[11]) / 10).ToString() + " Volts"+i;
i++;

现在为您提供页面名称,并通过绑定到这些属性来更新标签.

Now give you page a name and update labels by bindings to these properties.

<Page x:Name="CPUBaseMain ...
...
<Label x:Name="CPUClockSpeedText" Content="{Binding Speed, ElementName=CPUBaseMain}" ...
<Label x:Name="CPUCVoltageText" Content="{Binding Volt, ElementName=CPUBaseMain}" ...

这篇关于引发异常:WindowsBase.dll中的"System.InvalidOperationException"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆