2009-11-18 92 views
0

我已经写以下代码以执行某些并发HTTP发布和文件归档:通过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的消息的队列和张贴消息发送到web服务器。一旦发布消息,它将从此队列中出列,并添加到第二个队列中。线程3读取该队列,并简单地将XML写入文件。

我期望看到XML文件逐渐显示为处理消息队列(有时消息队列可能需要大约40分钟才能处理)。我实际看到的是没有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 
+1

您将需要显示“ProcessNTSMessageQueue”和“ProcessSuccessfulNTSMessageQueue”函数的代码。 – 2009-11-18 15:31:38

+0

感谢大家的帮助,这是我第一次进入线程,我不确定我在这个阶段做了什么! – Simon 2009-11-20 13:42:21

回答

3

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 
+0

我会这么说,这就是发生了什么 – 2009-11-18 15:45:31

+0

应该可能继续(或VB等效) – 2009-11-18 15:49:00

+0

这工作正如我想。非常感谢。 – Simon 2009-11-20 13:43:05

0

不,您不会误解代码;对我来说,看起来你的某个函数有一个bug(或者ProcessNTSMessageQueue不是以线程安全的方式编写的,因此不能并行化)。

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

2

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

检查事项:

  • 是您的队列线程?
  • 你是如何取得物品的?
  • 读者线程如何获得队列中新写入的通知?
+0

嗯,你的第三点是有趣的 - 我不知道它是否得到通知。 – Simon 2009-11-18 15:42:22

2

我@Jeff胸骨同意作为对可能出现的问题,即ProcessSuccessfulNTSMessageQueue()即将退出。

除此之外,它看起来像你有一个关于_SentMessageQueue变量的竞赛条件。在PostSuccessfulNTSMessageQueue()中,您锁定队列。但看起来队列是PostXMLToNTS()方法中创建的。如果是这种情况,那么如果尚未创建队列,那么您正在冒中的lock语句将抛出ArgumentNullException的风险。

另外,您不同步Enqueue()操作中的PostXMLToNTS()方法。这些需要同步,如Dequeue()操作在ProcessSuccessfulNTSMessageQueue()方法中。

+0

好的发现 - 我太过于狭隘地关注主要问题。这些也需要修复。 – 2009-11-18 17:40:03