c# - System.Drawing - 参数无效

标签 c# .net-4.0 bitmap system.drawing

经过更多测试后,我发现这个问题可能是由于图像以某种方式没有及时加载以克隆到位图中并显示。这可能吗?

注意:是的,标题中的这个错误还有其他问题,但从一些研究来看,它似乎是一个含糊不清的错误,有许多可能的原因。我还没有找到任何与我的场景相同的问题。

我收到以下错误。

System.ArgumentException was unhandled
HResult=-2147024809
Message=Parameter is not valid.
Source=System.Drawing

它源于这段代码。似乎是随机的(即,有时有效,有时无效。在不重新启动 VS 和重建项目的情况下连续运行的次数越多,失败的可能性就越大):

private Bitmap GetSprite(bool anim, int tsIndex, int tileIdx) {
    System.Drawing.Rectangle cloneRect;
    string prefix = (anim) ? "A" : "S";
    using (Bitmap b = new Bitmap(prefix + tsIndex.ToString() + ".png")) {
        if (anim) {
            cloneRect = new System.Drawing.Rectangle(BaseObjects.A_AnimSpriteSets[tsIndex].StaticRecs[tileIdx].X, BaseObjects.A_AnimSpriteSets[tsIndex].StaticRecs[tileIdx].Y, BaseObjects.A_AnimSpriteSets[tsIndex].RecWidth, BaseObjects.A_AnimSpriteSets[tsIndex].RecHeight);
        } else {
            cloneRect = new System.Drawing.Rectangle(BaseObjects.A_StaticSpriteSets[tsIndex].StaticRecs[tileIdx].X, BaseObjects.A_StaticSpriteSets[tsIndex].StaticRecs[tileIdx].Y, BaseObjects.A_StaticSpriteSets[tsIndex].RecWidth, BaseObjects.A_StaticSpriteSets[tsIndex].RecHeight);
        }
        return b.Clone(cloneRect, b.PixelFormat);
    }
}

具体来说,第四行:

using (Bitmap b = new Bitmap(prefix + tsIndex.ToString() + ".png"))

代码的简化目标是根据 spriteset 索引和 sprite 索引从 spriteset 返回包含 sprite 的位图。此位图显示在 PictureBox 中,直到它被更改为不同的图像。我知道这个逻辑是有效的;那不是这里的问题。我用来测试的 .png 是 384*256。

所有参数设置正确,所有引用文件都在那里,一切似乎都井井有条。最奇怪的是,它有时有效,有时无效。这让我相信它可能是 System.Drawing 本身的内存泄漏,但我似乎无法追踪它。

编辑:更新了代码并添加了 StackTrace。尽管在不再使用位图时对其进行了处理,但仍然存在相同的问题(有关如何处理位图的示例,请参见下面的代码)。

if (Sprite.Image != null) { Sprite.Image.Dispose(); }
    Sprite.Image = GetSprite(true, tsIdx, tileIdx);

堆栈跟踪:

System.ArgumentException was unhandled
  HResult=-2147024809
  Message=Parameter is not valid.
  Source=System.Drawing
  StackTrace:
       at System.Drawing.Bitmap..ctor(String filename)
       at CreationTool.Main.GetSprite(Boolean anim, Int32 tsIndex, Int32 tileIdx) in F:\~\~\CreationTool\Main.cs:line 420
       at CreationTool.Main.Input_EnemySprite_SelectedIndexChanged(Object sender, EventArgs e) in F:\~\~\CreationTool\Main.cs:line 107
       at System.Windows.Forms.ComboBox.OnSelectedIndexChanged(EventArgs e)
       at System.Windows.Forms.ComboBox.set_SelectedIndex(Int32 value)
       at CreationTool.States.State_Enemy.populateForm() in F:\~\~\CreationTool\States\State_Enemy.cs:line 28
       at CreationTool.States.State_Enemy.Load(String name) in F:\~\~\CreationTool\States\State_Enemy.cs:line 22
       at CreationTool.Main.btnLoad_Click(Object sender, EventArgs e) in F:\~\~\CreationTool\Main.cs:line 174
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at CreationTool.Program.Main() in F:\~\~\CreationTool\Program.cs:line 15
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()

最佳答案

哇,这段代码简直就是在泄漏句柄。需要dispose所有实现了IDisposable的类型,在System.Drawing assembly(GDI+)中有很多类型:

private Bitmap GetSprite(bool anim, int tsIndex, int tileIdx)
{
    Rectangle cloneRect;
    string prefix = (anim) ? "A" : "S";
    using (Bitmap b = new Bitmap(prefix + tsIndex.ToString() + ".png"))
    {
        if (anim)
        {
            cloneRect = new Rectangle(BaseObjects.A_AnimSpriteSets[tsIndex].StaticRecs[tileIdx].X, BaseObjects.A_AnimSpriteSets[tsIndex].StaticRecs[tileIdx].Y, BaseObjects.A_AnimSpriteSets[tsIndex].RecWidth, BaseObjects.A_AnimSpriteSets[tsIndex].RecHeight);
        }
        else
        {
            cloneRect = new Rectangle(BaseObjects.A_StaticSpriteSets[tsIndex].StaticRecs[tileIdx].X, BaseObjects.A_StaticSpriteSets[tsIndex].StaticRecs[tileIdx].Y, BaseObjects.A_StaticSpriteSets[tsIndex].RecWidth, BaseObjects.A_StaticSpriteSets[tsIndex].RecHeight);
        }

        return b.Clone(cloneRect, b.PixelFormat);
    }
}

还要确保通过将调用方包装在 using 语句中,您还可以处理此函数返回的位图:

using (Bitmap b = GetSprite(true, 0, 5))
{
    // do whatever you needed to do with the bitmap here
}

关于c# - System.Drawing - 参数无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14099246/

相关文章:

c# - 在 Timer 回调方法中使用 CancellationTokens

c# - 如何知道要使用 protobuf-net 反序列化的字节数组的长度?

c# - Autofac - ASP.NET Core Action 过滤器中的属性注入(inject)

c# - 生成随机字母数字代码 C#

c# - 我的 C# 应用程序要求我的用户安装 .net 4 - 我的项目中的目标框架是 2.0?

尝试将位图加载到 imageView 时出现 java.lang.OutOfMemoryError

java - 如何确定 64 位值中第 n 个最高有效位组的位置?

c# - C#中动态创建数组的方法

.net - 如何使用.NET CF在WebBrowser控件中获取所有页面的位图

c# - 将 Dictionary<string, string> 转换为单个聚合字符串表示的最佳方法?