4

我必须生成大尺寸的大图像,比如 15000x3000。我使用 GDI+ 类Bitmap生成这些图像。

当然,有时生成会失败,因为没有更多的内存来实例化Bitmap。我的目标是通知我的用户他们允许生成的图像的最大尺寸。

消息应如下所示:

您尝试生成大小为 15000x3000 的图像,但内存不足。可用的最大尺寸为 10000x3000 或 15000x1000。

创建消息的想法是这样的:

public bool CanCreateBitmap(Size size, out string message)
{
    long availableMemory = this.GetAvailableContiguousMemory();
    long bytesRequiered = (long)size.Width * size.Height * 32;

    if (availableMemory < bytesRequiered)
    {
        var sizeProposal1 = new Size(size.Width, (int)(availableMemory / (32 * size.Width)));
        var sizeProposal2 = new Size((int)(availableMemory / (32 * size.Height)), size.Height);

        message = string.Format("You tried to generate an image of size {0}, but there is not enough memory."
                + Environment.NewLine + "The maximum size available is {1}, or {2}."
                , size, sizeProposal1, sizeProposal2);

        return false;
    }
    else
    {
        message = "";
        return true;
    }
}

但我没有该函数的代码GetAvailableContiguousMemory()

有没有一种方法可以在.Net 中检索连续内存?
我是否提出了正确的问题来实现我的目标?

4

2 回答 2

3

这种通知是一种创可贴,实际上并不能帮助用户。他们真的很想创建那个大的位图,而一个任意小的位图并不是他们想要的。如果你仍然想这样做,那么你需要调用 VirtualQuery 来遍历虚拟地址空间并找到尚未映射的块。

现在再也没有这个问题了,将项目的平台目标设置更改为 AnyCPU,这样您的程序就可以使用 64 位操作系统上可用的大量虚拟内存空间。

于 2013-05-22T09:39:39.130 回答
3

没有这样的功能,因为问题“我可以分配多少内存”包含竞争条件。假设有一个你需要的函数,你调用它,它告诉你有大量的可用内存。您将其传达给用户,用户决定图像大小,然后您开始实际分配图像。但与此同时,其他一些进程占用了一半的可用内存,现在您的调用因 OutOfMemoryException 而中断。

TCP/IP 上的媒体流也有类似的问题。您想开始流式传输视频,但它需要相当多的网络带宽,并且您希望确保此带宽也将在几分钟后可用,因为仅启动视频流会适得其反当播放达到视频长度的三分之二时卡住。现在,通过在握手阶段保留网络资源解决了这个问题——即使你现在没有使用带宽(视频流还没有开始)。

好吧,您可能会尝试使用一些晦涩的 Windows API 调用来实现类似的效果。尝试从VirtualAlloc函数开始研究。但是,我不建议您走这条路,因为即使您的应用程序运行良好,也可能不稳定或不可靠或影响系统上的其他进程。特别是,这些 Windows API 是从 C++ 原生使用的,并且您正在使用 .NET 中的托管堆 - 我没有尝试过这种方法并且无法预测结果(但如果您成功,希望收到您的反馈! )。

您要问的是设计决策。我还推荐 dandan78 的方法 - 让用户选择图像大小,尝试创建它并在尝试失败时将错误反馈回来。用户最终会习惯他们的计算机的能力,并且不会经常将系统推到超出其限制的范围内。

编辑:您还应该记住一件事:没有“可用的连续内存”之类的东西。操作系统为您提供虚拟内存页面。这些页面在被引用时被加载到内存中。如果你要求大量内存,你会得到一堆页面,这些页面将在虚拟内存空间中分配连续的地址,这就是你会得到内存是连续的印象的方式。但是您通常有由语句返回的非连续内存位置,new因为内存管理器只返回托管堆上的第一个可用插槽。我知道这些笔记与这个问题无关,但在这种情况下牢记内存管理策略肯定不会有什么坏处。

于 2013-05-22T08:39:40.600 回答