代码之家  ›  专栏  ›  技术社区  ›  Simon

这段线程代码和我想的一样吗?

  •  0
  • Simon  · 技术社区  · 16 年前

    我编写了以下代码来同时执行HTTP发布和文件归档:

    Dim t1 As New Threading.Thread(New Threading.ThreadStart(AddressOf ProcessNTSMessageQueue))
    Dim t2 As New Threading.Thread(New Threading.ThreadStart(AddressOf ProcessNTSMessageQueue))
    Dim t3 As New Threading.Thread(New Threading.ThreadStart(AddressOf ProcessSuccessfulNTSMessageQueue))
    
    t1.Start()
    t2.Start()
    t3.Start()
    
    t1.Join()
    t2.Join()
    t3.Join()
    

    我有两条线(1&2) 读取XML消息队列并通过HTTP将消息发布到web服务器。消息发布后,它将从此队列中退出队列,并添加到第二个队列中。线程3读取该队列,并将XML直接写入文件。

    *编辑。以下是四个相关线程方法的代码:

    Private Sub ProcessNTSMessageQueue()
            While True
                Dim msg As String = Nothing
                SyncLock _MessageQueue
    
                    If _MessageQueue.Count > 0 Then
                        msg = _MessageQueue.Dequeue()
                    Else
                        Exit Sub
                    End If
    
                End SyncLock
    
                'Post the message
                'it's important to do this outside lock() 
                If msg <> Nothing Then
                    Me.PostXMLToNTS(msg)
                End If
            End While
    
        End Sub
    
    Private Sub ProcessSuccessfulNTSMessageQueue()
            While True
                Dim msg As String = Nothing
                SyncLock _SentMessageQueue
    
                    If _SentMessageQueue.Count > 0 Then
                        msg = _SentMessageQueue.Dequeue()
                    Else
                        Exit Sub
                    End If
    
                End SyncLock
    
                'Post the message
                'it's important to do this outside lock() 
                If msg <> Nothing Then
                    Me.ArchiveXMLAsFile(Guid.NewGuid.ToString, msg)
                    _SuccessfulMessageCount += 1
                End If
    
            End While
        End Sub
    
    Private Function PostXMLToNTS(ByVal XMLString As String) As Boolean
    
            Try
    
                Dim result As Net.HttpStatusCode = NTSPoster.PostXml(XMLString, _Settings.NTSPostURLCurrent, _Settings.NTSPostUsernameCurrent, _Settings.NTSPostPasswordCurrent)
    
                Select Case result
                    Case Net.HttpStatusCode.Accepted, Net.HttpStatusCode.OK 'Good
    
                        If _SentMessageQueue Is Nothing Then
                            _SentMessageQueue = New Queue(Of String)
                        End If
                        _SentMessageQueue.Enqueue(XMLString)
    
                        Return True
    
                    Case Else 'Probably bad
    
                        If _FailedMessageQueue Is Nothing Then
                            _FailedMessageQueue = New Queue(Of String)
                        End If
                        _FailedMessageQueue.Enqueue(XMLString)
    
                        Return False
    
                End Select
    
            Catch ex As Exception
                Throw
            End Try
        End Function
    
    Private Sub ArchiveXMLAsFile(ByVal name As String, ByVal XML As String)
    
            Try
                'Create directory in archive location based on todays date
                Dim dir As New DirectoryInfo(Me.TodaysXMLArchiveLocation)
    
                'If the directory does not already exist then create it
                If Not dir.Exists Then
                    dir.Create()
                End If
    
                Dim FileName As String = String.Format("{0}.xml", name)
                Using sw As StreamWriter = New StreamWriter(Path.Combine(dir.FullName, FileName))
                    sw.Write(XML)
                    sw.Close()
                End Using
    
            Catch ex As Exception
                Throw
            End Try
    
        End Sub
    
    4 回复  |  直到 16 年前
        1
  •  3
  •   Jeff Sternal    16 年前

    本节 ProcessSuccessfulNTSMessageQueue 第一次通过退出方法(并终止线程),因为线程开始时队列上可能没有任何消息:

    If _SentMessageQueue.Count > 0 Then
        msg = _SentMessageQueue.Dequeue()
    Else
        Exit Sub
    End If
    

    问题是,你怎么知道第三个线程何时完成,对吗?解决方案是在前两个线程完成时,使另一个类级别变量发出信号。在里面 ProcessNTSMessageQueue ,您可以在此处设置它:

    If _MessageQueue.Count > 0 Then
        msg = _MessageQueue.Dequeue()
    Else
        _IsStartQueueEmpty = True;
        Exit Sub
    End If
    

    而且 ProcessSuccessfulNTSMessageQueue

    If _SentMessageQueue.Count > 0 Then
        msg = _SentMessageQueue.Dequeue()
    Else
        If _IsStartQueueEmpty Then
            Exit Sub
    End If
    
        2
  •  2
  •   Jorge Córdoba    16 年前

    如果ProcessNTSMessageQueue和ProcessSuccessfulNTSMessageQueue的代码正确,您应该可以看到预期的结果。

    检查事项:

    • 您的队列是线程安全的吗?
    • 读线程如何得到队列中新写入的通知?
        3
  •  2
  •   Matt Davis    16 年前

    关于可能的问题,我同意@Jeff Sternal的观点,即 ProcessSuccessfulNTSMessageQueue()

    除此之外,看起来你有一个关于比赛的比赛条件 _SentMessageQueue PostSuccessfulNTSMessageQueue() ,您将锁定队列。但看起来排队的人太多了 创建 在 PostXMLToNTS() 方法。如果是这种情况,那么您将面临以下风险: lock 声明 ProcessSuccessfulNTSMessageQueue() 威尔扔了一个 ArgumentNullException 如果尚未创建队列。

    Enqueue() PostXMLToNTS() 方法。这些需要像 Dequeue() 手术正在进行中 ProcessSuccessfulNTSMessageQueue() 方法。

        4
  •  0
  •   Heinzi    16 年前

    不,你没有误解代码;在我看来,您的一个函数(或 ProcessNTSMessageQueue

    您是否尝试过在Visual Studio中单步执行代码?您可以点击暂停按钮,然后从工具栏的下拉列表中选择一个线程。

    推荐文章