【问题标题】:System.OutOfMemoryException when allocating large size array分配大尺寸数组时出现 System.OutOfMemoryException
【发布时间】:2014-09-17 06:30:18
【问题描述】:

在我将文件上传到 FTP 网站的 vb 应用程序中,我使用大尺寸数组。在声明数组的过程中,有时我会收到Exception of type 'System.OutOfMemoryException' was thrown.

之类的错误

我已将数组声明为

Const BufferSize As Integer = 400000000
Dim content(BufferSize - 1) As Byte

实际上 400000000 大约是 380 MB 。我有 4 GB RAM,使用率不高。为什么有时会显示此错误?怎么解决?

【问题讨论】:

  • 为您的应用程序分配了多少内存?这才是最重要的,而不是系统总内存。
  • @jmcilhinney 你的意思是应用程序有多少内存使用(来自任务管理器)?

标签: arrays vb.net out-of-memory


【解决方案1】:

参考我之前的same questionanswer(感谢Aik 的出色解释)。

即使您有 4gb 内存,也无法知道您有 380mb 的连续可用空间。如果您的 RAM 碎片太大,这可能会导致问题。

你需要丢弃你的数据来解决这个问题(见answer...)

AIK 的解释:

例如在我的机器上我不能分配超过 908 000 000 一个数组中的字节,但我可以分配 100 * 90 800 000 没有任何 如果它存储在更多数组中会出现问题:

Dim toBigArray As Byte() = New Byte(908000000) {}
'doesn't work (6 zeroes after 908)
' allocation in more arrays
Dim a As Byte()() = New Byte(100)() {}

For i As Integer = 0 To a.Length - 1
    ' it works even there is 10x more memory needed than before
        ' (5 zeroes after 908) 
    a(0) = New Byte(90800000) {}
Next

【讨论】:

  • 如果我按照你在答案中所说的那样做,那么我如何在 Filestrem 中使用这个二维数组。读取功能。它接受一维数组。
  • 我试图说明的一点是,您可以将太多内存分配到单个数组中。你最终会让自己陷入困境(例如,看看你的问题)。您必须将其分块(如下面的代码示例中所示)。您可以手动调整缓冲区大小以获得最佳速度。
【解决方案2】:

使用这么大的数组是个坏主意。您可以分小块流式传输文件。这是来自link的一些示例代码

''' <summary>
''' Methods to upload file to FTP Server
''' </summary>
''' <param name="_FileName">local source file name</param>
''' <param name="_UploadPath">Upload FTP path including Host name</param>
''' <param name="_FTPUser">FTP login username</param>
''' <param name="_FTPPass">FTP login password</param>

Public Sub UploadFile(ByVal _FileName As String, ByVal _UploadPath As String, ByVal _FTPUser As String, ByVal _FTPPass As String)
Dim _FileInfo As New System.IO.FileInfo(_FileName)

' Create FtpWebRequest object from the Uri provided
Dim _FtpWebRequest As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(New Uri(_UploadPath)), System.Net.FtpWebRequest)

' Provide the WebPermission Credintials
_FtpWebRequest.Credentials = New System.Net.NetworkCredential(_FTPUser, _FTPPass)

' By default KeepAlive is true, where the control connection is not closed
' after a command is executed.
_FtpWebRequest.KeepAlive = False

' set timeout for 20 seconds
_FtpWebRequest.Timeout = 20000

' Specify the command to be executed.
_FtpWebRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile

' Specify the data transfer type.
_FtpWebRequest.UseBinary = True

' Notify the server about the size of the uploaded file
_FtpWebRequest.ContentLength = _FileInfo.Length

' The buffer size is set to 2kb
Dim buffLength As Integer = 2048
Dim buff(buffLength - 1) As Byte

' Opens a file stream (System.IO.FileStream) to read the file to be uploaded
Dim _FileStream As System.IO.FileStream = _FileInfo.OpenRead()

Try
' Stream to which the file to be upload is written
Dim _Stream As System.IO.Stream = _FtpWebRequest.GetRequestStream()

' Read from the file stream 2kb at a time
Dim contentLen As Integer = _FileStream.Read(buff, 0, buffLength)

' Till Stream content ends
Do While contentLen <> 0
' Write Content from the file stream to the FTP Upload Stream
_Stream.Write(buff, 0, contentLen)
contentLen = _FileStream.Read(buff, 0, buffLength)
Loop

' Close the file stream and the Request Stream
_Stream.Close()
_Stream.Dispose()
_FileStream.Close()
_FileStream.Dispose()
Catch ex As Exception
MessageBox.Show(ex.Message, "Upload Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub


HOW TO USE:  

 ' Upload file using FTP
   UploadFile("c:\UploadFile.doc", "ftp://FTPHostName/UploadPath/UploadFile.doc", "UserName", "Password")

编辑 1:

试试这些链接可能对你有帮助。

1)My.Computer.Network.UploadFile

2)Improve Performance of FtpWebRequest

【讨论】:

  • 在我使用 2048 作为 buffLength 之前。但是上传会很慢。我也测试过。如果我将 2048 设置为 buffLength,则上传一个 100 MB 的文件需要 18 分钟,如果 buffLength 为 400000000 且具有相同的网速,则只需 3 分钟
猜你喜欢
  • 1970-01-01
  • 2017-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-16
  • 1970-01-01
相关资源
最近更新 更多