2009-11-18 95 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