aldiablo
12-09-2005, 19:20
Ciao
qualcuno sà spiegarmi, con precisione, come faccio a usare + thread in "parallelo" in modo asincrono, in VB.net?
Ho consultato un pò di documentazione ma nulla che fa al caso mio.
Grazie
aldiablo
Anche a me prima o poi piacerebbe buttarmi in qualche test...intanto ho trovato questo esempio, non sò se già l'avevi trovato anche te:
È possibile scrivere applicazioni che consentono di eseguire più attività contemporaneamente. Questa caratteristica, detta multithreading o free threading, è il sistema ideale per progettare componenti che utilizzano il processore in modo intensivo e richiedono l'input dell'utente. Un esempio di componente che fa uso di multithreading può essere rappresentato da un componente per il calcolo delle informazioni sugli stipendi. Il componente è in grado di elaborare i dati immessi in un database da un utente su un thread mentre i calcoli degli stipendi, che richiedono un utilizzo intensivo del processore, vengono eseguiti su un altro thread. Eseguendo i processi su thread separati, gli utenti non dovranno attendere che il computer completi i calcoli per immettere nuovi dati. In questa procedura viene creato un componente multithreading semplice in grado di effettuare contemporaneamente diversi calcoli complessi.
Creazione del progetto
L'applicazione è costituita da un unico form e un componente. L'utente immetterà i valori, segnalando al componente di avviare i calcoli. Il form riceverà i valori dal componente e li visualizzerà nei controlli label. Il componente eseguirà quindi i calcoli, che richiedono un utilizzo intensivo del processore, e ne segnalerà il completamento al form. Sarà necessario creare delle variabili pubbliche nel componente per contenere i valori ricevuti dall'interfaccia utente e si dovranno inoltre implementare i metodi per l'esecuzione dei calcoli sulla base dei valori di tali variabili.
Nota Sebbene per un metodo che calcola un valore sia in genere preferibile una funzione, gli argomenti non possono essere passati tra i thread e i valori non possono essere restituiti. Esistono molti sistemi semplici per fornire valori ai thread e ricevere valori da questi ultimi. In questa dimostrazione, la restituzione dei valori all'interfaccia utente verrà ottenuta mediante l'aggiornamento delle variabili pubbliche e si utilizzeranno eventi per notificare al programma principale il completamento dell'esecuzione da parte di un thread.
Per creare il form
Creare un nuovo progetto selezionando il modello Applicazione Windows.
Denominare l'applicazione Calculations e rinominare Form1.vb come frmCalculations.vb.
Il form fungerà da interfaccia utente primaria per l'applicazione.
Aggiungere cinque controlli Label, quattro controlli Button e un controllo TextBox al form. Impostare le proprietà per questi controlli come indicato di seguito.Controllo Nome Testo
Label1 lblFactorial1 (vuoto)
Label2 lblFactorial2 (vuoto)
Label3 lblAddTwo (vuoto)
Label4 lblRunLoops (vuoto)
Label5 lblTotalCalculations (vuoto)
Button1 btnFactorial1 Factorial
Button2 btnFactorial2 Factorial - 1
Button3 btnAddTwo Add Two
Button4 btnRunLoops Run a Loop
TextBox1 txtValue (vuoto)
Per creare il componente Calculator
Scegliere Aggiungi componente dal menu Progetto.
Denominare il componente Calculator.
Per aggiungere variabili pubbliche al componente Calculator
Aprire l'editor di codice per Calculator.
Aggiungere le istruzioni necessarie per la creazione delle variabili pubbliche che verranno utilizzate per passare i valori da frmCalculations a ciascun thread.
La variabile varTotalCalculations conserverà un totale parziale del numero totale di calcoli effettuati dal componente, mentre le altre variabili riceveranno i valori dal form.
Public varAddTwo As Integer
Public varFact1 As Integer
Public varFact2 As Integer
Public varLoopValue As Integer
Public varTotalCalculations As Double = 0
Per aggiungere metodi ed eventi al componente Calculator
Dichiarare gli eventi che il componente utilizzerà per comunicare i valori al form. Immediatamente sotto le dichiarazioni delle variabili immesse nel passaggio precedente, digitare il seguente codice:
Public Event FactorialComplete(ByVal Factorial As Double, ByVal _
TotalCalculations As Double)
Public Event FactorialMinusComplete(ByVal Factorial As Double, ByVal _
TotalCalculations As Double)
Public Event AddTwoComplete(ByVal Result As Integer, ByVal _
TotalCalculations As Double)
Public Event LoopComplete(ByVal TotalCalculations As Double, ByVal _
Counter As Integer)
Immediatamente sotto le dichiarazioni delle variabili immesse nel passaggio 1, digitare il seguente codice:
' This sub will calculate the value of a number minus 1 factorial
' (varFact2-1!).
Public Sub FactorialMinusOne()
Dim varX As Integer = 1
Dim varTotalAsOfNow As Double
Dim varResult As Double = 1
' Performs a factorial calculation on varFact2 - 1.
For varX = 1 to varFact2 - 1
varResult *= varX
' Increments varTotalCalculations and keeps track of the current
' total as of this instant.
varTotalCalculations += 1
varTotalAsOfNow = varTotalCalculations
Next varX
' Signals that the method has completed, and communicates the
' result and a value of total calculations performed up to this
' point
RaiseEvent FactorialMinusComplete(varResult, varTotalAsOfNow)
End Sub
' This sub will calculate the value of a number factorial (varFact1!).
Public Sub Factorial()
Dim varX As Integer = 1
Dim varResult As Double = 1
Dim varTotalAsOfNow As Double = 0
For varX = 1 to varFact1
varResult *= varX
varTotalCalculations += 1
varTotalAsOfNow = varTotalCalculations
Next varX
RaiseEvent FactorialComplete(varResult, varTotalAsOfNow)
End Sub
' This sub will add two to a number (varAddTwo + 2).
Public Sub AddTwo()
Dim varResult As Integer
Dim varTotalAsOfNow As Double
varResult = varAddTwo + 2
varTotalCalculations += 1
varTotalAsOfNow = varTotalCalculations
RaiseEvent AddTwoComplete(varResult, varTotalAsOfNow)
End Sub
' This method will run a loop with a nested loop varLoopValue times.
Public Sub RunALoop()
Dim varX As Integer
Dim varY As Integer
Dim varTotalAsOfNow As Double
For varX = 1 To varLoopValue
' This nested loop is added solely for the purpose of slowing
' down the program and creating a processor-intensive
' application.
For varY = 1 To 500
varTotalCalculations += 1
varTotalAsOfNow = varTotalCalculations
Next
Next
RaiseEvent LoopComplete(varTotalAsOfNow, varX - 1)
End Sub
Trasferimento dell'input dell'utente al componente
Il passaggio successivo prevede l'aggiunta a frmCalculations del codice che consente di ricevere l'input dell'utente e di trasferire e ricevere valori al e dal componente Calculator.
Per implementare la funzionalità front-end in frmCalculations
Aprire frmCalculations nell'editor di codice.
Individuare l'istruzione Inherits System.Windows.Forms.Form. Immediatamente sotto di essa digitare:
Dim WithEvents Calculator1 As Calculator
Individuare Public Sub New(). Immediatamente prima dell'istruzione End Sub aggiungere la riga seguente:
' Creates a new instance of Calculator.
Calculator1 = New Calculator
Individuare l'istruzione End Class nella parte inferiore dell'editor di codice. Immediatamente prima di questa istruzione, aggiungere il codice seguente per gestire i clic dei pulsanti:
Protected Sub btnFactorial1_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles btnFactorial1.Click
' Passes the value typed in the txtValue to Calculator.varFact1.
Calculator1.varFact1 = CInt(txtValue.Text)
' Disables the btnFactorial1 until this calculation is complete.
btnFactorial1.Enabled = False
Calculator1.Factorial()
End Sub
Protected Sub btnFactorial2_Click(ByVal sender As Object, ByVal e _
As System.EventArgs) Handles btnFactorial2.Click
Calculator1.varFact2 = CInt(txtValue.Text)
btnFactorial2.Enabled = False
Calculator1.FactorialMinusOne()
End Sub
Protected Sub btnAddTwo_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles btnAddTwo.Click
Calculator1.varAddTwo = CInt(txtValue.Text)
btnAddTwo.Enabled = False
Calculator1.AddTwo()
End Sub
Protected Sub btnRunLoops_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles btnRunLoops.Click
Calculator1.varLoopValue = CInt(txtValue.Text)
btnRunLoops.Enabled = False
' Lets the user know that a loop is running.
lblRunLoops.Text = "Looping"
Calculator1.RunALoop()
End Sub
Sotto il codice aggiunto nel passaggio precedente, digitare il codice riportato di seguito per gestire gli eventi che il form riceverà da Calculator1:
Protected Sub FactorialHandler(ByVal Value As Double, ByVal _
Calculations As Double)
' Displays the returned value in the appropriate label.
lblFactorial1.Text = Value.ToString
' Re-enables the button so it can be used again.
btnFactorial1.Enabled = True
' Updates the label that displays the total calculations performed
lblTotalCalculations.Text = "TotalCalculations are " & _
Calculations.ToString
End Sub
Protected Sub Factorial1Handler(ByVal Value As Double, ByVal _
Calculations As Double)
lblFactorial2.Text = Value.ToString
btnFactorial2.Enabled = True
lblTotalCalculations.Text = "TotalCalculations are " & _
Calculations.ToString
End Sub
Protected Sub AddTwoHandler(ByVal Value As Integer, ByVal _
Calculations As Double)
lblAddTwo.Text = Value.ToString
btnAddTwo.Enabled = True
lblTotalCalculations.Text = "TotalCalculations are " & _
Calculations.ToString
End Sub
Protected Sub LoopDoneHandler(ByVal Calculations As Double, ByVal _
Count As Integer)
btnRunLoops.Enabled = True
lblRunLoops.Text = Count.ToString
lblTotalCalculations.Text = "TotalCalculations are " & _
Calculations.ToString
End Sub
Nel costruttore di frmCalculations aggiungere il seguente codice immediatamente prima della riga End Sub per gestire gli eventi personalizzati che il form riceverà da Calculator1:
AddHandler Calculator1.FactorialComplete, AddressOf FactorialHandler
AddHandler Calculator1.AddTwoComplete, AddressOf AddTwoHandler
AddHandler Calculator1.FactorialMinusComplete, AddressOf _
Factorial1Handler
AddHandler Calculator1.LoopComplete, AddressOf LoopDoneHandler
Con queste istruzioni si aggiungono i gestori di eventi per la gestione degli eventi personalizzati che il form riceverà da Calculator1. L'operatore AddressOf crea un delegato per la routine specificata, mentre l'istruzione AddHandler designa tale delegato per la gestione dell'evento specificato.
Test dell'applicazione
A questo punto è stato creato un progetto che incorpora un form e un componente in grado di eseguire diversi calcoli complessi. Sebbene non sia stata ancora implementata la funzionalità multithreading, prima di procedere sarà necessario eseguire il test del progetto per verificarne le funzionalità.
Per eseguire il test del progetto
Scegliere Avvia dal menu Debug. L'applicazione viene avviata e verrà visualizzato frmCalculations.
Nella casella di testo immettere 4, quindi fare clic sul pulsante con etichetta Add two.
Nell'etichetta sottostante dovrebbe apparire il numero "6", mentre in lblTotalCalculations dovrebbe essere visualizzata l'indicazione "Total Calculations are 1".
Fare clic sul pulsante con etichetta Factorial - 1.
Nell'etichetta sotto il pulsante verrà visualizzato il numerale "6", mentre in lblTotalCalculations verrà visualizzato il messaggio "Total Calculations are 4".
Modificare il valore nella casella di testo in 20, quindi fare clic sul pulsante con etichetta Factorial.
Sotto il pulsante verrà visualizzato il numero "2.43290200817664E+18" e in lblTotalCalculations verrà visualizzato il messaggio "Total Calculations are 24".
Modificare il valore nella casella di testo in 50000, quindi fare clic sul pulsante con etichetta RunALoop.
Si noti come prima della riattivazione di questo pulsante intercorra un intervallo breve ma percettibile. Nell'etichetta sotto questo pulsante viene visualizzato "50000" e i calcoli totali visualizzati sono "25000024".
Modificare il valore nella casella di testo in 5000000 e fare clic sul pulsante con etichetta Run A Loop, quindi fare immediatamente clic sul pulsante con etichetta Add Two. Fare di nuovo clic sul pulsante.
Il pulsante non risponderà, analogamente a qualsiasi altro controllo del form, finché i cicli non saranno completati.
Se nel programma viene eseguito un singolo thread di esecuzione, i calcoli che richiedono un utilizzo intensivo del processore, riportati nell'esempio precedente, tenderanno a bloccare il programma fino a quando non verranno completati. Nella sezione successiva verrà aggiunta la funzionalità multithreading all'applicazione in modo da consentire l'esecuzione simultanea di più thread.
Aggiunta della funzionalità multithreading
Nell'esempio precedente sono state illustrate le limitazioni delle applicazioni con un singolo thread di esecuzione. Nella sezione successiva verrà utilizzata la Classe Thread per aggiungere al componente più thread di esecuzione.
Per aggiungere la subroutine Threads
Aprire Calculator.vb nell'editor di codice. Nella parte superiore del codice individuare la riga Inherits System.ComponentModel.Component. Immediatamente sotto di essa digitare il seguente codice:
' Declares the variables you will use to hold your thread objects.
Public FactorialThread As System.Threading.Thread
Public FactorialMinusOneThread As System.Threading.Thread
Public AddTwoThread As System.Threading.Thread
Public LoopThread As System.Threading.Thread
Immediatamente prima dell'istruzione End Class nella parte inferiore del codice, aggiungere il seguente metodo:
Public Sub ChooseThreads(ByVal threadNumber As Integer)
' Determines which thread to start based on the value it receives.
Select Case threadNumber
Case 1
' Sets the thread using the AddressOf the subroutine where
' the thread will start.
FactorialThread = New System.Threading.Thread(AddressOf _
Factorial)
' Starts the thread.
FactorialThread.Start()
Case 2
FactorialMinusOneThread = New _
System.Threading.Thread(AddressOf FactorialMinusOne)
FactorialMinusOneThread.Start()
Case 3
AddTwoThread = New System.Threading.Thread(AddressOf AddTwo)
AddTwoThread.Start()
Case 4
LoopThread = New System.Threading.Thread(AddressOf RunALoop)
LoopThread.Start()
End Select
End Sub
La creazione di un'istanza di un oggetto Thread richiede un argomento sotto forma di oggetto ThreadStart. L'oggetto ThreadStart è un delegato che fa riferimento all'indirizzo della subroutine in cui il thread verrà avviato. Un oggetto ThreadStart non può accettare parametri o passare valori e non può quindi indicare una funzione. L'operatore AddressOf restituisce un delegato che funge da oggetto ThreadStart. La subroutine ChooseThreads appena implementata riceverà un valore dal programma dal quale viene chiamata e utilizzerà tale valore per determinare il thread appropriato da avviare.
Per aggiungere il codice di avvio dei thread a frmCalculations
Aprire il file frmCalculations.vb nell'editor di codice. Individuare Sub btnFactorial1_Click.
Impostare come commento la riga che chiama direttamente il metodo Calculator1.Factorial come indicato di seguito.
' Calculator1.Factorial
Aggiungere la riga seguente per chiamare il metodo Calculator1.ChooseThreads:
' Passes the value 1 to Calculator1, thus directing it to start the ' correct thread.
Calculator1.ChooseThreads(1)
Apportare modifiche simili alle altre subroutine button_click.
Nota Assicurarsi di includere il valore appropriato per l'argomento threads.
Al termine, il codice dovrebbe risultare simile al seguente:
Protected Sub btnFactorial1_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles btnFactorial1.Click
' Passes the value typed in the txtValue to Calculator.varFact1.
Calculator1.varFact1 = CInt(txtValue.Text)
' Disables the btnFactorial1 until this calculation is complete.
btnFactorial1.Enabled = False
' Calculator1.Factorial()
' Passes the value 1 to Calculator1, thus directing it to start the
' Correct thread.
Calculator1.ChooseThreads(1)
End Sub
Protected Sub btnFactorial2_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles btnFactorial2.Click
Calculator1.varFact2 = CInt(txtValue.Text)
btnFactorial2.Enabled = False
' Calculator1.FactorialMinusOne()
Calculator1.ChooseThreads(2)
End Sub
Protected Sub btnAddTwo_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles btnAddTwo.Click
Calculator1.varAddTwo = CInt(txtValue.Text)
btnAddTwo.Enabled = False
' Calculator1.AddTwo()
Calculator1.ChooseThreads(3)
End Sub
Protected Sub btnRunLoops_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles btnRunLoops.Click
Calculator1.varLoopValue = CInt(txtValue.Text)
btnRunLoops.Enabled = False
' Lets the user know that a loop is running.
lblRunLoops.Text = "Looping"
' Calculator1.RunALoop()
Calculator1.ChooseThreads(4)
End Sub
Marshalling delle chiamate ai controlli
In questa sezione verrà illustrato come agevolare l'aggiornamento degli elementi visualizzati nel form. Poiché i controlli appartengono sempre al thread principale di esecuzione, qualsiasi chiamata a un controllo da un thread subordinato richiede una chiamata di marshalling. Per marshalling si intende lo spostamento di una chiamata oltre i limiti dei thread, operazione molto dispendiosa in termini di risorse. Per ridurre la quantità di marshalling richiesta e per assicurarsi che le chiamate vengano gestite in modo thread-safe, è necessario utilizzare il metodo Control.BeginInvoke per richiamare i metodi sul thread di esecuzione principale, riducendo in tal modo il marshalling che è necessario effettuare oltre i limiti dei thread. Questo tipo di chiamata è necessaria quando si chiamano metodi che modificano i controlli. Per ulteriori informazioni, vedere Manipolazione dei controlli dai thread.
Per creare routine per le chiamate ai controlli
Aprire l'editor di codice per frmCalculations. Nella sezione delle dichiarazioni aggiungere il codice seguente:
Public Delegate Sub FHandler(ByVal Value As Double, ByVal _
Calculations As Double)
Public Delegate Sub A2Handler(ByVal Value As Integer, ByVal _
Calculations As Double)
Public Delegate Sub LDhandler(ByVal Calculations As Double, ByVal _
Count As Integer)
Invoke e BeginInvoke richiedono come argomento un delegato per il metodo appropriato. In queste righe vengono dichiarate le firme dei delegati che verranno utilizzate da BeginInvoke per richiamare i metodi appropriati.
Aggiungere al codice i metodi vuoti riportati di seguito.
Public Sub FactHandler(ByVal Value As Double, ByVal Calculations As _
Double)
End Sub
Public Sub Fact1Handler(ByVal Value As Double, ByVal Calculations As _
Double)
End Sub
Public Sub Add2Handler(ByVal Value As Integer, ByVal Calculations As _
Double)
End Sub
Public Sub LDoneHandler(ByVal Calculations As Double, ByVal Count As _
Integer)
End Sub
Scegliere Taglia e Incolla dal menu Modifica per tagliare tutto il codice da Sub FactorialHandler e incollarlo in FactHandler.
Ripetere il passaggio precedente per Factorial1Handler e Fact1Handler, AddTwoHandler e Add2Handler e LoopDoneHandler e LDoneHandler.
Al termine, non deve rimanere alcun codice in FactorialHandler, Factorial1Handler, AddTwoHandler e LoopDoneHandler, e tutto il codice precedentemente contenuto in tali metodi deve essere stato spostato correttamente nei nuovi metodi.
Chiamare il metodo BeginInvoke per richiamare i metodi in modo asincrono. È possibile chiamare BeginInvoke dal form (me) o da qualsiasi controllo del form:
Protected Sub FactorialHandler(ByVal Value As Double, ByVal _
Calculations As Double)
' BeginInvoke causes asynchronous execution to begin at the address
' specified by the delegate. Simply put, it transfers execution of
' this method back to the main thread. Any parameters required by
' the method contained at the delegate are wrapped in an object and
' passed.
Me.BeginInvoke(New FHandler(AddressOf FactHandler), New Object() _
{Value, Calculations})
End Sub
Protected Sub Factorial1Handler(ByVal Value As Double, ByVal _
Calculations As Double)
Me.BeginInvoke(New FHandler(AddressOf Fact1Handler), New Object() _
{Value, Calculations})
End Sub
Protected Sub AddTwoHandler(ByVal Value As Integer, ByVal _
Calculations As Double)
Me.BeginInvoke(New A2Handler(AddressOf Add2Handler), New Object() _
{Value, Calculations})
End Sub
Protected Sub LoopDoneHandler(ByVal Calculations As Double, ByVal _
Count As Integer)
Me.BeginInvoke(New LDHandler(AddressOf Ldonehandler), New Object() _
{Calculations, Count})
End Sub
Apparentemente il gestore eventi effettua semplicemente una chiamata al metodo successivo, ma in realtà viene richiamato un metodo sul thread principale dell'operazione. Questo approccio consente di evitare l'esecuzione di chiamate oltre i limiti dei thread e consente un'esecuzione efficiente delle applicazioni multithreading senza causarne il blocco. Per informazioni dettagliate sull'utilizzo dei controlli in un ambiente multithreading, vedere Manipolazione dei controlli dai thread
Salvare il lavoro.
Per eseguire il test della soluzione, scegliere Avvia dal menu Debug.
Digitare 10000000 nella casella di testo e fare clic su Run A Loop.
Nell'etichetta sotto il pulsante viene visualizzato "Looping". L'esecuzione di questo ciclo dovrebbe richiedere parecchio tempo. Se viene completata troppo presto, modificare il numero di conseguenza.
Fare clic in rapida successione su tutti e tre i pulsanti ancora attivati. Tutti i pulsanti risponderanno all'input. Il primo risultato dovrebbe essere visualizzato nell'etichetta sotto il pulsante Add Two. I risultati successivi verranno visualizzati nelle etichette sotto i pulsanti Factorial. I risultati restituiti corrispondono a un numero infinito, in quanto il numero restituito da un Factorial pari a 10.000.000 è troppo grande per essere contenuto in una variabile in precisione doppia. Infine, dopo un ulteriore ritardo, i risultati verranno restituiti sotto il pulsante Run A Loop.
Come si è potuto osservare, quattro diversi calcoli sono stati eseguiti contemporaneamente su quattro thread distinti, l'interfaccia utente ha continuato a rispondere all'input e i risultati sono stati restituiti al completamento di ciascun thread.
Coordinamento dei thread
Un utente esperto di applicazioni multithreading sarà in grado individuare dei piccoli difetti nel codice digitato. Richiamare le righe di codice da ciascuna subroutine per l'esecuzione dei calcoli in Calculator.vb:
varTotalCalculations += 1
varTotalAsOfNow = varTotalCalculations
Queste due righe di codice consentono di incrementare la variabile pubblica varTotalCalculations e di impostare la variabile locale varTotalAsOfNow su tale valore. Il valore viene quindi restituito a frmCalculations e visualizzato in un controllo label. Il valore restituito rappresenta il valore corretto solo nel caso in cui sia in esecuzione un singolo thread di esecuzione. Se al contrario si utilizzano più thread, il valore restituito potrebbe non essere corretto. Ogni thread, infatti, incrementa la variabile varTotalCalculations ed è possibile che, se un thread ha incrementato la variabile ma il valore non è ancora stato copiato in varTotalAsOfNow, un altro thread intervenga a incrementare la variabile alterandone il valore. È quindi possibile che ciascun thread restituisca risultati imprecisi. In Visual Basic è disponibile l'istruzione SyncLock per consentire la sincronizzazione dei thread al fine di assicurare che ciascun thread restituisca sempre risultati corretti. La sintassi per SyncLock è la seguente:
SyncLock AnObject
Insert code that affects the object
Insert some more
Insert even more
' Release the lock
End SyncLock
Quando si inserisce il blocco SyncLock, l'esecuzione della specifica espressione viene bloccata fino a quando il thread specificato detiene un blocco esclusivo sull'oggetto in questione. Nell'esempio sopra riportato, l'esecuzione viene bloccata su AnObject. È necessario utilizzare SyncLock con un oggetto che restituisca un riferimento anziché un valore. L'esecuzione può quindi precedere come blocco senza interferenze da parte di altri thread. Un insieme di istruzioni che vengono eseguite come unità costituisce un'operazione atomica. Quando si individua l'istruzione End SyncLock, l'espressione viene liberata e viene consentita la normale esecuzione dei thread.
Per aggiungere l'istruzione SyncLock all'applicazione
Aprire Calculator.vb nell'editor di codice.
Individuare tutte le istanze del seguente codice:
varTotalCalculations += 1
varTotalAsOfNow = varTotalCalculations
Dovrebbero essere presenti quattro istanze, una per ciascun metodo di calcolo.
Modificare questo codice in modo simile a quanto riportato di seguito:
SyncLock Me
varTotalCalculations += 1
varTotalAsOfNow = varTotalCalculations
End SyncLock
Salvare il lavoro ed eseguirne il test come nell'esempio precedente.
Si noterà un lieve calo delle prestazioni del programma in quanto l'esecuzione dei thread viene interrotta quando si ottiene un blocco esclusivo del componente. Sebbene garantisca accuratezza, questo approccio non consente di avvalersi del livello di prestazioni più elevato garantito da più thread. Si consiglia quindi di valutare attentamente la necessità di bloccare i thread e di implementare i blocchi solo quando è assolutamente necessario.
Vedere anche
Programmazione con i componenti | Procedura dettagliata: modifica di un componente | Multithreading nei componenti | Coordinamento di più thread di esecuzione | Procedura dettagliata: modifica di componenti multithreading semplici con Visual C#
--------------------------------------------------------------------------------
Invia commenti su questo argomento a Microsoft
© Microsoft Corporation. Tutti i diritti riservati.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.