Ich habe eine Klasse, die zwei Methoden enthält, ruft eine Klasse, die eine Anzahl von Threads erstellt und ausführt, die andere ist ein Ereignishandler, der ein Ereignis behandelt, wenn diese Threads ausgelöst werden vollständig (und ruft dann die erste Methode erneut auf).Wo und was in diesem Code zu synchronisieren Sperre
Ich verstehe, dass die Methode, die das Ereignis behandelt, in dem Thread ausgeführt wird, der das Ereignis ausgelöst hat. So als solche ich SyncLock eine Membervariable, die besagt, wie viele Threads laufen und subtrahieren davon:
SyncLock Me //GetType(me)
_availableThreads -= 1
End SyncLock
Also habe ich ein paar Fragen:
Haupt Frage: Soll ich SyncLock‘werden _availableThreads überall in der Klasse ing - also in der Methode, die die Fäden (die 1 hinzufügt, wenn ein Thread erstellt wird) erzeugt
Side Fragen zu dieser Frage bezogen werden:
Ich würde normalerweise die aktuelle Instanz synchronisieren, aber ich habe Code gesehen, der stattdessen den Typ SyncLocks, also was ist der Unterschied zwischen Synchronisierungsverriegelung
Me
(Aktuelle Instanz) undGetType(me)
?Würde es einen Leistungsunterschied zwischen den beiden geben? und gibt es etwas kleineres, das ich für das oben Gesagte sperren könnte, was nichts anderes betrifft - vielleicht ein separates "Vorhängeschloss" -Objekt, das nur zum Zwecke der Blockierung von Dingen in einer Klasse erstellt wurde?
Hinweis: Der einzige Zweck der _available Threads zu steuern, wie viele Threads zu einem bestimmten Zeitpunkt ausgeführt werden kann und die Threads verarbeiten Aufträge, die Stunden dauern kann, laufen.
Code:
Public Class QManager
Private _maxThreadCount, _availableThreads As Integer
Public Sub New(ByVal maxThreadCount As Integer)
Me.MaximumThreadCount = maxThreadCount
End Sub
Public Sub WorkThroughQueue()
//get jobs from queue (priorities change, so call this every time)
Dim jobQ As Queue(Of QdJobInfo) = QueueDAO.GetJobList
//loop job queue while there are jobs and we have threads available
While jobQ.Count > 0 And _availableThreads <= _maxThreadCount
//create threads for each queued job
Dim queuedJob As New QdJob(jobQ.Dequeue)
AddHandler queuedJob.ThreadComplete, AddressOf QueuedJob_ThreadCompleted
_availableThreads += 1 //use a thread up (do we need a sync lock here?)***************************
queuedJob.Process() //go process the job
End While
//when we get here, don't do anything else - when a job completes it will call this method again
End Sub
Private Sub QueuedJob_ThreadCompleted(ByVal sender As QdJobInfo, ByVal args As EventArgs)
SyncLock Me //GetType(me)
_availableThreads -= 1
End SyncLock
//regardless of how the job ended, we want to carry on going through the rest of the jobs
WorkThroughQueue()
End Sub
#Region "Properties"
Public Property MaximumThreadCount() As Integer
Get
Return _maxThreadCount
End Get
Set(ByVal value As Integer)
If value > Environment.ProcessorCount * 2 Then
_maxThreadCount = value
Else
value = Environment.ProcessorCount
End If
LogFacade.LogInfo(_logger, "Maximum Thread Count set to " & _maxThreadCount)
End Set
End Property
#End Region
End Class
Sehr interessant ... Ich war von der Sperrungs Klasse nicht bekannt. Vielen Dank. –
Guter Punkt über die Warteschlange - ich benutze 3,5, also ist das leider nicht möglich. Ist es möglich, dem Thread wieder beizutreten und die erste Methode aufzurufen? Würdest du wissen, wie das geht? - möglicherweise mit thread.join? –
@Mr Shoubs: Nein, nicht wirklich. Wenn Sie 3.5 verwenden, empfehle ich die Verwendung eines SyncLock für ein privates Objekt für den Zugriff auf die Warteschlange - sowohl für die Warteschlange als auch für die Warteschlange. –