vb.net中的线程,信号量和outofmemory异常 [英] Thread , semaphore and outofmemory exception in vb.net

查看:89
本文介绍了vb.net中的线程,信号量和outofmemory异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用以下代码我得到OutOfMemory错误,我注意到新线程是连续启动的,我如何控制线程数或重用以前创建的?我哪里错了? Hothanks



Using the following code I get the OutOfMemory error, I noticed that new threads are started continuously, how do I control the number of threads or reuse previously created? where am I wrong? Hothanks

Module Module1

Dim TotalThread As Integer = 3
Dim SemaphoreCount As Integer = 2
Dim Threads As Thread() = New Thread(TotalThread - 1) {}
Dim semaph As New Semaphore(SemaphoreCount, SemaphoreCount)

Private baseUrl As String = "http://www.domain.com"
Private m_SavePath As String = "c:\test\"

Public Structure ParameterList
    Public ImageUrl As String
    Public FileName As String
    Public objSemaphore As Semaphore
End Structure

<MTAThread> _
Sub Main()
   checkImage() 
End Sub

Private Function checkImage() As Boolean

    Dim _param As New ParameterList

    Dim dbConn As New SqlClient.SqlConnection("Data Source=localhost\sqlexpress;Initial Catalog=db;Persist Security Info=True;User ID=username;Password=password")
    dbConn.Open()
    Dim cmd As New SqlCommand
    cmd.Connection = dbConn
    cmd.CommandType = CommandType.Text
    cmd.CommandText = "SELECT  LinkImg.codice , LinkImg.foto , LinkImg.Zoom FROM LinkImg WHERE codice NOT IN (select codice from _PRODOTTI_IMMAGINI)"

    Dim dtr As SqlDataReader

    Try
        dtr = cmd.ExecuteReader(CommandBehavior.CloseConnection)

        If dtr.HasRows Then
            While dtr.Read

                Dim t1 As New Thread(New ParameterizedThreadStart(AddressOf DownloadRemoteImageFile))
                Dim t2 As New Thread(New ParameterizedThreadStart(AddressOf DownloadRemoteImageFile))

                _param.ImageUrl = dtr("zoom")
                _param.FileName = "img_zoom_" & dtr("codice").ToString.Trim & ".jpg"
                _param.objSemaphore = semaph

                t1.IsBackground = True
                t1.Start(_param)

                _param.ImageUrl = dtr("foto")
                _param.FileName = "img_Small_" & dtr("codice").ToString.Trim & ".jpg"
                _param.objSemaphore = semaph

                t2.IsBackground = True
                t2.Start(_param)

                t1 = Nothing
                t2 = Nothing

            End While
        End If

    Catch ex As Exception
        Throw ex
    Finally
        dbConn.Close()
    End Try

    Return True
End Function

Public Sub DownloadRemoteImageFile(ByVal param As Object)

    Dim l_SemaPhore As Semaphore = DirectCast(param.objSemaphore, Semaphore)

    If l_SemaPhore.WaitOne(100, False) Then
        Try
            Dim imageUrl As String = baseUrl & param.ImageUrl

            Dim imageBytes As Byte()
            Dim imageRequest As HttpWebRequest = DirectCast(WebRequest.Create(imageUrl), HttpWebRequest)
            Dim imageResponse As HttpWebResponse = TryCast(imageRequest.GetResponse(), HttpWebResponse)

            If (imageResponse.StatusCode = HttpStatusCode.OK OrElse imageResponse.StatusCode = HttpStatusCode.Moved OrElse imageResponse.StatusCode = HttpStatusCode.Redirect) AndAlso imageResponse.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase) Then
                Dim responseStream As Stream = imageResponse.GetResponseStream()

                Using br As New BinaryReader(responseStream)
                    imageBytes = br.ReadBytes(500000)
                    br.Close()
                End Using

                responseStream.Close()
                imageResponse.Close()

                Dim fs As FileStream
                Dim bw As BinaryWriter

                Try
                    fs = New FileStream(m_SavePath & param.FileName.Replace("/", "-"), FileMode.Create)
                    bw = New BinaryWriter(fs)

                    bw.Write(imageBytes)
                Catch ex As Exception

                Finally
                    If fs IsNot Nothing Then fs.Close()
                    If bw IsNot Nothing Then bw.Close()
                End Try

                Thread.Sleep(200)

            End If

        Finally
            l_SemaPhore.Release()
        End Try
    End If
End Sub
End Module

推荐答案

为什么要在eavry记录读取时启动一对新线程?每个线程都有成本。旋转起来很昂贵,并且为它的堆栈花费1MB内存。



谷歌的任务类并转换此代码来改变任务。任务只会使用足够的线程来保持处理器的繁忙,并且无需执行任何特殊操作即可管理自己的工作队列。
Why are you starting a pair of new threads on eavry record read? Every thread comes with a cost. They are expensive to spin up and cost you 1MB of memory for its stack.

Google for "Task class" and convert this code to spin up a Task instead. Tasks will only use enough threads to keep the processor busy and manage its own queue of work to be done without you doing anything special.


这篇关于vb.net中的线程,信号量和outofmemory异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆