2014-11-04 3 views
0

Я не уверен, что я делаю неправильно. У меня есть простая программа, использующая пул потоков для выполнения 9 задач. Каждая задача запускает три новых потока для извлечения данных. Затем вызывающий поток обрабатывает результаты. Все они должны выполняться с разным временем, а затем выводят результаты в ближайшее окно. Но не все задачи фактически выводят что-либо. Обычно я получаю 7-8 результатов. Я не могу предсказать, какие результаты будут выводиться; он случайный. Почему не все результаты выводятся?Многопоточность не выводит все

Class Work3 

    Sub mainLoop() 

     Dim callback As New WaitCallback(AddressOf DoOneCustomer) 

     For loopCt As Integer = 1 To 9 

      'Data in 
      Dim dataIn As New DataIn("Cust" & loopCt, loopCt) 

      'run code on the thread pool 
      ThreadPool.QueueUserWorkItem(callback, dataIn) 

     Next 

    End Sub 

    Function DoOneCustomer(ByVal DataIn2 As Object) As Boolean 
     Dim DataIn As DataIn = CType(datain2, Datain) 

     Dim Tub As New DataContainer(DataIn.CustID, DataIn.Int) 

     'start new data threads 
     'get data in parallel 
     Dim t1 As New Thread(AddressOf GetData1) 
     Dim t2 As New Thread(AddressOf GetData2) 
     Dim t3 As New Thread(AddressOf GetData3) 
     t1.Start(Tub) 
     t2.Start(Tub) 
     t3.Start(Tub) 

     'join all three threads to ensure finished getting data 
     t1.Join() 
     t2.Join() 
     t3.Join() 

     If MakeDecision(Tub) Then 

      'process results in-line; no new thread 
      doProcessData(Tub) 

     End If 

     Return True 

    End Function 

    Function MakeDecision(ByRef Tub As DataContainer) As Boolean 
     Return True 
    End Function 

    Sub doProcessData(ByVal myTub As DataContainer) 

     Debug.Print(myTub.Data1.QBName & _ 
        " End bal: " & myTub.Data1.EndBal.ToString("#,##0") & _ 
        " Inv1 " & myTub.Data2.Total.ToString("#,##0") & _ 
        " Inv2 " & myTub.Data3.Total.ToString("#,##0")) 
    End Sub 

    Sub GetData1(ByVal myTub2 As Object) 
     Dim myTub As dataContainer = CType(myTub2, DataContainer) 
     Dim d As New DetailData 
     d.QBName = myTub.CustID 
     d.BeginBal = myTub.Int * 10000 + myTub.Int 
     d.EndBal = myTub.Int * 100000 + myTub.Int 
     Dim Num As Integer = Calculate(myTub.Int) 

     'put data 
     myTub.Data1 = d 
    End Sub 
    Sub GetData2(ByVal myTub2 As Object) 
     Dim myTub As dataContainer = CType(myTub2, DataContainer) 
     Dim inv As New InvoiceData 
     inv.QbCustName = myTub.CustID 
     inv.TxnDate = DateAdd(DateInterval.Day, New Random(1).Next(1, 30), Now) 
     inv.Total = myTub.Int * 1000 + myTub.Int 
     Dim Num As Integer = Calculate(myTub.Int) 

     'put data 
     myTub.Data2 = inv 
    End Sub 
    Sub GetData3(ByVal myTub2 As Object) 
     Dim myTub As dataContainer = CType(myTub2, DataContainer) 
     Dim inv As New InvoiceData 
     inv.QbCustName = myTub.CustID 
     inv.TxnDate = DateAdd(DateInterval.Day, New Random(1).Next(1, 30), Now) 
     inv.Total = myTub.Int * 100 
     Dim Num As Integer = Calculate(myTub.Int) 

     'put data 
     myTub.Data3 = inv 
    End Sub 

End Class 

Class DataIn 
    Public Int As Integer 
    Public CustID As String 
    Public Sub New(ByVal _CustID As String, ByVal _Int As Integer) 
     Int = _Int 
     CustID = _CustID 
    End Sub 
    Public Sub New() 
    End Sub 
End Class 

Class DataContainer 
    Public Int As Integer 
    Public CustID As String 
    Public Data1 As DetailData 
    Public Data2 As InvoiceData 
    Public Data3 As InvoiceData 
    Public Sub New(ByVal _CustID As String, ByVal _Int As Integer) 
     Int = _Int 
     CustID = _CustID 
    End Sub 
    Public Sub New() 
    End Sub 
End Class 

Class DetailData 
    Public QBName As String 
    Public BeginBal As Decimal 
    Public EndBal As Decimal 
End Class 

Class InvoiceData 
    Public QbCustName As String 
    Public TxnDate As Date 
    Public Total As Decimal 
End Class 

'calculate fibonacci to increase calculation time by varying amounts 
Public Function Calculate(ByVal n As Integer) As Integer 
    If n <= 1 Then 
     Return n 
    End If 
    Return Calculate(n - 1) + Calculate(n - 2) 
End Function 

Выход выглядит следующим образом

Cust1 End bal: 100,001 Inv1 1,001 Inv2 100 
Cust4 End bal: 400,004 Inv1 4,004 Inv2 400 
Cust2 End bal: 200,002 Inv1 2,002 Inv2 200 
Cust7 End bal: 700,007 Inv1 7,007 Inv2 700 
Cust6 End bal: 600,006 Inv1 6,006 Inv2 600 
Cust5 End bal: 500,005 Inv1 5,005 Inv2 500 
Cust8 End bal: 800,008 Inv1 8,008 Inv2 800 
Cust9 End bal: 900,009 Inv1 9,009 Inv2 900 

.Net fiddle

+0

в 'DoOneCustomer', это' Tub' или 'tub'? – didierc

+0

Предполагается, что это 'Tub'. Это имеет значение в VB.net? В любом случае я изменил его и получил те же результаты. –

+0

вам, вероятно, нужен вызов функции, чтобы дождаться завершения всех потоков пула (а не программиста vb, я не знаю API). – didierc

ответ

0

Я думаю, что проблема с Debug.Print. Я считаю, что использование Debug.Print для оценки моего кода было ошибочной идеей. Почему я должен думать, что окно отладки может обрабатывать несколько одновременных входных данных.

При использовании MsgBox в качестве выхода код выполняет, как ожидалось. Все данные выводятся. Несколько окон Msgbox не являются проблемой для VB.net.

Я также попытался поставить Thread.Sleep в коде. С этим он отлично работает. Предположительно, это потому, что вывод больше не ударяет по окну отладки одновременно.

Таким образом, проблема заключается не в коде, а как с устройством вывода. Код должен быть переписан для учета ограничений выходного устройства.

Смежные вопросы