C# 引发异常:';系统无效操作异常';在WindowsBase.dll中

C# 引发异常:';系统无效操作异常';在WindowsBase.dll中,c#,.net,wpf,xaml,C#,.net,Wpf,Xaml,我在WPF UI中更新某些内容时遇到问题。引发异常的代码的同一部分在另一个函数中工作得很好。现在,由于某种原因,我不知道它不仅抛出了一个异常,它也没有像我希望的那样进行更新。我希望OnCPUDetEvent()函数中的UI元素根据我设置的计时器进行更新 这是我的密码: using System; using System.Collections.Generic; using System.Management.Instrumentation; using System.Management; u

我在WPF UI中更新某些内容时遇到问题。引发异常的代码的同一部分在另一个函数中工作得很好。现在,由于某种原因,我不知道它不仅抛出了一个异常,它也没有像我希望的那样进行更新。我希望
OnCPUDetEvent()
函数中的UI元素根据我设置的计时器进行更新

这是我的密码:

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


}
使用系统;
使用System.Collections.Generic;
使用系统、管理、仪器;
使用制度管理;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用系统计时器;
使用System.Runtime.Serialization;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
命名空间HWDetCS
{
/// 
///CPUBase.xaml的交互逻辑
/// 
公共部分类CPUBase:第页
{
//列表比数组好,适合我!
公共列表名称=新列表();
公共列表值=新列表();
公共整数i=0;
//设置稍后启用的计时器
公共计时器CPUDetRefreshTimer;
公共CPUBase()
{
//自动生成的东西,不要碰!
初始化组件();
//实际运行所有的检测工具
CPUDet();
//启动计时器,准备好
CPUDetRefreshTimer=新计时器();
CPUDetRefreshTimer.AutoReset=true;
CPUDetRefreshTimer.Interval=500;
CPUDetRefreshTimer.Enabled=true;
CPUDetRefreshTimer.appeased+=OnCPUDetEvent;
}
//这东西能做所有的工作
公共无效CPUDet()
{
//获取CPU管理类,这使它成为我们从中获取信息的CPU,而不是什么都没有,因为如果它没有设置为CPU,它会出错、崩溃并哭泣很多…不要更改它。
ManagementClass CPUClass=新的ManagementClass(“Win32_处理器”);
CPUClass.Options.UseAmendedQualifiers=true;
//设置一个数据收集来获取数据,这件事和下一件事永远不应该在一个循环中!它会像气球一样打碎你的CPU!
PropertyDataCollection dataCollection=CPUClass.Properties;
//获取类的实例,由于某些原因,这是必需的,不要触摸,不要将其放入循环为什么你不能听!?
ManagementObjectCollection instanceCollection=CPUClass.GetInstances();
//这是一个循环,非常脆弱,不要碰它,它会得到我们正在收集的数据列表
foreach(数据集合中的PropertyData属性)
{
//将名称添加到一个可读的列表中!
Name.Add(property.Name);
//循环遍历所有实例并从中获取实际数据
foreach(instanceCollection中的ManagementObject实例)
{
//确保我们不会出现空引用错误,我非常讨厌这些错误!我知道它是空的,闭嘴!
if(instance.Properties[property.Name.ToString()].Value==null)
{
//如果为null,则不要添加实际的属性数据,而是添加一个表示null的字符串,以便我们知道不要弄乱它
添加(“空”);
}
其他的
{
//否则,请继续
Add(instance.Properties[property.Name.ToString()].Value.ToString());
}
}
//数。。。。
i++;
}
//调试东西,不要发布未注释的!
//TODO:评论一下!
对于(int x=0;x
以下是实际UI页面的XAML:

<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元素

此链接中描述了这一点:

上面的链接给出了解决问题的方法。然而,对于您的问题没有单一的解决方案。以下只是其中之一。它会逐步进行您需要应用的更改。(编辑:我在下一个答案中添加了另一个解决方案)


使用System.ComponentModel添加
到您的标题。这是使用具有更改属性的绑定。如果需要,添加引用dll文件<
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}
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));
    }
}
Speed = values[10] + "MHz"+i;
Volt = (Convert.ToDouble(values[11]) / 10).ToString() + " Volts"+i;
i++;
<Page x:Name="CPUBaseMain ...
...
<Label x:Name="CPUClockSpeedText" Content="{Binding Speed, ElementName=CPUBaseMain}" ...
<Label x:Name="CPUCVoltageText" Content="{Binding Volt, ElementName=CPUBaseMain}" ...
using System.Windows.Threading;
Action dispatcherAction = new Action(() =>
  {
    // Get the current clock speed
    CPUClockSpeedText.Content = values[10] + "MHz";
    // Get the current Voltage
    CPUCVoltageText.Content = (Convert.ToDouble(values[11]) / 10).ToString() + " Volts";
  });
this.Dispatcher.Invoke(dispatcherAction, DispatcherPriority.Normal);
this.Dispatcher.Invoke(
    new Action (() =>
        {
            // Get the current clock speed
            CPUClockSpeedText.Content = values[10] + "MHz";
            // Get the current Voltage
            CPUCVoltageText.Content = (Convert.ToDouble(values[11]) / 10).ToString() + " Volts";
        }),
    DispatcherPriority.Normal                
    );