Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 代码优化在使用PeekMessage时导致空引用异常_C#_Nullreferenceexception_Peekmessage - Fatal编程技术网

C# 代码优化在使用PeekMessage时导致空引用异常

C# 代码优化在使用PeekMessage时导致空引用异常,c#,nullreferenceexception,peekmessage,C#,Nullreferenceexception,Peekmessage,我正在使用gamedev.stackexchange线程中讨论的游戏循环: 若我使用的是调试构建类型,那个么一切都运行得很好,但当我执行发布时,会出现一个空引用异常。看起来只有在启用代码优化时才会发生这种情况。这是一个赤裸裸的例子,做同样的事情。表单完全为空,在本例中没有按钮/控件 using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; name

我正在使用gamedev.stackexchange线程中讨论的游戏循环:

若我使用的是调试构建类型,那个么一切都运行得很好,但当我执行发布时,会出现一个空引用异常。看起来只有在启用代码优化时才会发生这种情况。这是一个赤裸裸的例子,做同样的事情。表单完全为空,在本例中没有按钮/控件

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Sharp8
{
    public partial class DebugForm : Form
    {
        public DebugForm()
        {
            InitializeComponent();
            Application.Idle += GameLoop;
        }

        private void GameLoop(object sender, EventArgs e)
        {
            while (IsApplicationIdle())
            {
                Console.WriteLine("Game Updates/Rendering!"); 
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct NativeMessage
        {
            public IntPtr Handle;
            public uint Message;
            public IntPtr WParameter;
            public IntPtr LParameter;
            public uint Time;
            public Point Location;
        }

        [DllImport("user32.dll")]
        static extern bool PeekMessage(out Message message, IntPtr window, uint messageFilterMinimum, uint messageFilterMaximum, uint shouldRemoveMessage);

        private bool IsApplicationIdle()
        {
            Message result;
            return !PeekMessage(out result, IntPtr.Zero, 0, 0, 0);
        }
    }
}
当我运行此程序时,异常会发生在forms.dll内部的外部代码中,并在启动此窗体的Application.run(“etc”)之后抛出。堆栈跟踪并没有真正的帮助,它只是Application.Run和一堆外部代码

我不确定这是什么原因造成的,但我知道这与调用PeekMessage有关,因为如果我注释掉空闲事件的订阅,则不会发生错误


作为一个附带问题,为什么我需要在这里声明“NativeMessage”结构?如果我剪掉它,它似乎不会引起问题,但是使用这个游戏循环的每个例子都包括它。

peek消息上的
out
应该是
ref
peek消息
不会为您分配消息结构,它会填充您传入的消息结构。不同的是,
ref
参数在传入方法调用之前必须初始化,其中
out
参数不需要初始化。您将看到,当将
out
更改为
ref
时,编译器将强制您添加
new
调用以初始化
结果

在处理这个问题时,我发现只需将调用添加到
newmessage()
以初始化
result
,并将参数保留为
out
就足以防止崩溃。我假设在优化代码时,没有为
result
分配内存,从而导致对
peek消息的调用失败

[DllImport("user32.dll")]
static extern bool PeekMessage(ref Message message, IntPtr window, uint    messageFilterMinimum, uint messageFilterMaximum, uint shouldRemoveMessage);

private bool IsApplicationIdle()
{
    Message result = new Message();
    return !PeekMessage(ref result, IntPtr.Zero, 0, 0, 0);
}

peek消息上的
out
应该改为
ref
peek消息
不会为您分配消息结构,它会填充您传入的消息结构。不同的是,
ref
参数在传入方法调用之前必须初始化,其中
out
参数不需要初始化。您将看到,当将
out
更改为
ref
时,编译器将强制您添加
new
调用以初始化
结果

在处理这个问题时,我发现只需将调用添加到
newmessage()
以初始化
result
,并将参数保留为
out
就足以防止崩溃。我假设在优化代码时,没有为
result
分配内存,从而导致对
peek消息的调用失败

[DllImport("user32.dll")]
static extern bool PeekMessage(ref Message message, IntPtr window, uint    messageFilterMinimum, uint messageFilterMaximum, uint shouldRemoveMessage);

private bool IsApplicationIdle()
{
    Message result = new Message();
    return !PeekMessage(ref result, IntPtr.Zero, 0, 0, 0);
}
虽然正确地解释了如何解决代码中的
PeekMessage
问题,但我建议不要为此使用
PeekMessage
,因为它会带来一些不必要的开销。改用:

有关更多详细信息,请查看我的。

虽然正确解释了如何解决代码中的
PeekMessage
问题,但我建议不要为此使用
PeekMessage
,因为它会带来一些不必要的开销。改用:


有关更多详细信息,请查看我的。

能否将代码缩减为显示行为的简短可编译示例?完成,这是符合我意思的最精简示例。Console.WriteLine是我的emulator更新/呈现的地方。你能把代码简化为一个简短的可编译示例来展示这种行为吗?完成了,这是我所说的最精简的示例。Console.WriteLine是我的emulator更新/呈现的地方。这非常有趣,在emulator中,任何性能提升都不应该被忽略。感谢您提供了另一种解决方案,我将仔细研究您提供的链接。这非常有趣,在模拟器中,任何性能提升都不应被忽视。谢谢你提供了另一种解决方案,我会仔细研究你提供的链接。仔细检查后,这实际上并不能解决问题。它可以很好地编译,但在运行时仍然抛出nullreference异常。我尝试将它保留为“out”,并预先初始化对象,还尝试通过ref进行初始化。我仍然得到相同的崩溃。仔细检查后,这实际上并不能解决问题。它可以很好地编译,但在运行时仍然抛出nullreference异常。我尝试将它保留为“out”,并预先初始化对象,还尝试通过ref进行初始化。我仍然得到相同的崩溃。