Procedura: restare in attesa del completamento di una o più attività
In questo esempio viene mostrato come utilizzare il metodo Wait o il relativo metodo equivalente nella classe Task<TResult> per restare in attesa di una singola attività. Viene inoltre mostrato come utilizzare i metodi WaitAll e WaitAny statici per restare in attesa di più attività.
Esempio
' How to: Wait on One or More Tasks to Complete
Imports System.Threading
Imports System.Threading.Tasks
Module WaitOnTasks
Dim rand As New Random()
Sub Main()
' Wait on a single task with no timeout specified.
Dim taskA = Task.Factory.StartNew(Sub() DoSomeWork(10000000))
taskA.Wait()
Console.WriteLine("taskA has completed.")
' Wait on a single task with a timeout specified.
Dim taskB = Task.Factory.StartNew(Sub() DoSomeWork(10000000))
taskB.Wait(100) 'Wait for 100 ms.
If (taskB.IsCompleted) Then
Console.WriteLine("taskB has completed.")
Else
Console.WriteLine("Timed out before task2 completed.")
End If
' Wait for all tasks to complete.
Dim myTasks(9) As Task
For i As Integer = 0 To myTasks.Length - 1
myTasks(i) = Task.Factory.StartNew(Sub() DoSomeWork(10000000))
Next
Task.WaitAll(myTasks)
' Wait for first task to complete.
Dim tasks2(2) As Task(Of Double)
' Try three different approaches to the problem. Take the first one.
tasks2(0) = Task(Of Double).Factory.StartNew(Function() TrySolution1())
tasks2(1) = Task(Of Double).Factory.StartNew(Function() TrySolution2())
tasks2(2) = Task(Of Double).Factory.StartNew(Function() TrySolution3())
Dim index As Integer = Task.WaitAny(tasks2)
Dim d As Double = tasks2(index).Result
Console.WriteLine("task(0) completed first with result of {1}.", index, d)
Console.ReadKey()
End Sub
' Dummy Functions to Simulate Work
Function DoSomeWork(ByVal val As Integer)
' Pretend to do something.
Thread.SpinWait(val)
End Function
Function TrySolution1()
Dim i As Integer = rand.Next(1000000)
' Simulate work by spinning
Thread.SpinWait(i)
Return i
End Function
Function TrySolution2()
Dim i As Integer = rand.Next(1000000)
' Simulate work by spinning
Thread.SpinWait(i)
Return i
End Function
Function TrySolution3()
Dim i As Integer = rand.Next(1000000)
' Simulate work by spinning
Thread.SpinWait(i)
Thread.SpinWait(1000000)
Return i
End Function
End Module
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static Random rand = new Random();
static void Main(string[] args)
{
// Wait on a single task with no timeout specified.
Task taskA = Task.Factory.StartNew(() => DoSomeWork(10000000));
taskA.Wait();
Console.WriteLine("taskA has completed.");
// Wait on a single task with a timeout specified.
Task taskB = Task.Factory.StartNew(() => DoSomeWork(10000000));
taskB.Wait(100); //Wait for 100 ms.
if (taskB.IsCompleted)
Console.WriteLine("taskB has completed.");
else
Console.WriteLine("Timed out before taskB completed.");
// Wait for all tasks to complete.
Task[] tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
tasks[i] = Task.Factory.StartNew(() => DoSomeWork(10000000));
}
Task.WaitAll(tasks);
// Wait for first task to complete.
Task<double>[] tasks2 = new Task<double>[3];
// Try three different approaches to the problem. Take the first one.
tasks2[0] = Task<double>.Factory.StartNew(() => TrySolution1());
tasks2[1] = Task<double>.Factory.StartNew(() => TrySolution2());
tasks2[2] = Task<double>.Factory.StartNew(() => TrySolution3());
int index = Task.WaitAny(tasks2);
double d = tasks2[index].Result;
Console.WriteLine("task[{0}] completed first with result of {1}.", index, d);
Console.ReadKey();
}
static void DoSomeWork(int val)
{
// Pretend to do something.
Thread.SpinWait(val);
}
static double TrySolution1()
{
int i = rand.Next(1000000);
// Simulate work by spinning
Thread.SpinWait(i);
return DateTime.Now.Millisecond;
}
static double TrySolution2()
{
int i = rand.Next(1000000);
// Simulate work by spinning
Thread.SpinWait(i);
return DateTime.Now.Millisecond;
}
static double TrySolution3()
{
int i = rand.Next(1000000);
// Simulate work by spinning
Thread.SpinWait(i);
Thread.SpinWait(1000000);
return DateTime.Now.Millisecond;
}
}
Per semplicità, in questi esempi non viene mostrato il codice relativo alla gestione delle eccezioni né quello relativo all'annullamento. Poiché l'attesa è il meccanismo con cui il codice del programma gestisce le eccezioni generate da qualsiasi attività, nella maggior parte dei casi è necessario includere un metodo Wait in un blocco try-catch. Per ulteriori informazioni, vedere Procedura: gestire le eccezioni generate dalle attività. Se l'attività è annullabile, prima di tentare di utilizzare l'attività o la relativa proprietà Result() è necessario verificare la proprietà IsCanceled o IsCancellationRequested(). Per ulteriori informazioni, vedere Procedura: annullare un'attività e i relativi figli.
Vedere anche
Concetti
Espressioni lambda in PLINQ e TPL