Buonasera a tutti
sto eseguendo un processo di calcolo multithread della funzione myfunction_name utilizzando il BackgroundWorker. PEr capire quando i thread sono tutti terminati utilizzo un vettore inizializzato tutto a -100 che viene scritto da ciascun thread al termine della sua esecuzione, quando non ci sono più meno -100 il calcolo è finito.
Il mio codice è il seguente
Private Sub Launch()
Dim i, j, j_end As Integer
Dim ff(swarmSize - 1) As Double
Dim e As SwarmEvaluationFunction
'Lancio i thread multipli di indice j
For j = 0 To swarmSize - 1
For i = 0 To numConstraints
'Savataggio del valore indicatore di mancato calcolo:
f1Array(j, 0) = -100
Next
'Argomento di ingresso con predisposizione indice di particella e valori funzione di pesatura
e = New SwarmEvaluationFunction
ReDim e.f_target(numConstraints)
e.index_particle = j
StartWorkers(e)
Next
'Loop per determinare la conclusione di tutti i thread
j_end = 0
Do While Not j_end = -1
For j = 0 To swarmSize - 1
ff(j) = f1Array(j, 0)
Next
j_end = Array.FindIndex(ff, Function(p As Double) p < -99)
Loop
End Sub
Private m_WorkerList As New List(Of BackgroundWorker)
Private Sub StartWorkers(ByVal SwarmEvalFunc As SwarmEvaluationFunction)
Dim worker As New BackgroundWorker()
AddHandler worker.DoWork, AddressOf DoJob
AddHandler worker.RunWorkerCompleted, AddressOf JobDone
worker.WorkerSupportsCancellation = True
m_WorkerList.Add(worker)
worker.RunWorkerAsync(SwarmEvalFunc)
End Sub
Private Sub DoJob(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
'Console.WriteLine("eseguo thread N° "& DirectCast(e.Argument, Integer))
Dim k As Integer
Dim xx(numVariables - 1) As Double
Dim ff(numConstraints) As Double
Dim mySwarmEvalFunc As SwarmEvaluationFunction = DirectCast(e.Argument, SwarmEvaluationFunction)
With mySwarmEvalFunc
For k = 0 To numVariables - 1
xx(k) = swarmPos(.index_particle, k)
Next
'Funzione di calcolo
Call myfunction_name(xx, .f_target, .index_particle, myobjArr)
'Salvo in stringa
e.Result = CStr(.index_particle) & ";"& String.Join(";", .f_target)
End With
End Sub
Private Sub JobDone(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
Dim str As String = DirectCast(e.Result, String)
Dim strArr() As String
Dim k As Integer
Dim index_particle As Integer
strArr = str.Split(";")
index_particle = CInt(strArr(0))
For k = 0 To numConstraints
'Salvataggio dell'array su matrice risultati:
f1Array(index_particle, k) = CDbl(strArr(k + 1))
Next
End Sub
[f1Array,swarmPos ed altre variabili non dichiarate sono delle proprietà della classe che contiene il codice riportato]
In breve la sub Launch lancia i vari thread e poi entra in ciclo while in cui attende che tutti i risultati siano caricati dalla sub JobDone associata all'evento RunWorkerCompleted nella matrice f1Array.
Il problema consta nel fatto che in un progetto di tipo Console funziona tutto perfettamente e se metto un punto di debug in JobDone vedo che il programma si arresta all'interno, Se passo ad progetto Windows form per ogni thread viene eseguita solo la sub DoJob ma mai la JobDone ed il programma rimane bloccato nel while di Launch. La cosa pare confermata se guardo la lista dei processi m_WorkerList, in cui verifico che rimagono con la proprietà IsBusy=True (contrariamente al caso console in cui man mano che si realizzano gli eventi di completamente IsBusy diventano False).
Qualcuno sa cortesemente darmi una dritta?
Grazie
Luca