Definition
A Task represents an Asynchronous Operation.
It basis of many new features of .net 4, a particular useful one is The Task Parallel Library (TPL).
It is also used by the Asynchronous Methods seen in the AsyncCTP. (Not covered in this tutorial)
Dim myTask As System.Threading.Tasks.Task - Think of theses as a Sub
Dim myTask As System.Threading.Tasks.Task(Of T) - Think of these as a Function
Task.WaitAll
Imports System.Threading.Tasks
Imports System.Threading
Module Module1
Sub Main()
Dim rnd As New Random
Dim myTask0 As New Task(Sub()
For x = 0 To 50
Console.WriteLine(x)
Thread.Sleep(100)
Next
End Sub)
' Start the task run.
myTask0.Start()
Dim myTask1 As New Task(Of String)(Function()
Dim rw As Integer
SyncLock rnd
rw = 1000 ' rnd.NextDouble * 10000
End SyncLock
Thread.Sleep(rw)
Return String.Format("A waited {0} ms", rw)
End Function)
Dim myTask2 As New Task(Of String)(Function()
Dim rw As Integer
SyncLock rnd
rw = 10000 ' rnd.NextDouble * 10000
End SyncLock
Thread.Sleep(rw)
Return String.Format("B waited {0} ms", rw)
End Function)
' Create an array containing the tasks.
Dim tasks() = {myTask1, myTask2}
' Set them running.
Array.ForEach(tasks, Sub(tx) tx.Start())
Console.WriteLine("Using .WaitAny")
' We're going to wait for the first task to finish.
Dim rt = Task.WaitAny(tasks)
' if it returns Threading.Timeout.Infinite (Currently set to -1), it mean none finished.
If rt <> Threading.Timeout.Infinite Then
Console.WriteLine("Task {0} finished first", rt)
Console.WriteLine(tasks(rt).Result)
End If
Console.ReadKey()
If myTask0.IsCompleted = False Then
Console.WriteLine("Waiting For MyTask0 to finish")
myTask0.Wait()
End If
Task.WaitAll
Console.WriteLine()
Console.WriteLine("Using .WaitAll")
' Set them running.
myTask1 = New Task(Of String)(Function()
Dim rw As Integer
SyncLock rnd
rw = 1000 ' rnd.NextDouble * 10000
End SyncLock
Thread.Sleep(rw)
Return String.Format("A waited {0} ms", rw)
End Function)
myTask2 = New Task(Of String)(Function()
Dim rw As Integer
SyncLock rnd
rw = 10000 ' rnd.NextDouble * 10000
End SyncLock
Thread.Sleep(rw)
Return String.Format("B waited {0} ms", rw)
End Function)
tasks = {myTask1, myTask2}
' Create an array containing the tasks.
Array.ForEach(tasks, Sub(tx) tx.Start())
Console.WriteLine("Waiting")
Task.WaitAll(tasks)
Console.WriteLine("Wait Done")
For Each tsk In tasks
Select Case True
Case tsk.IsCanceled
Case tsk.IsFaulted
Case tsk.IsCompleted
Console.WriteLine(tsk.Result)
Case Else
End Select
Next
A Cancel-able Task
Cancellation in Task is cooperative, which means it isn't automatic and the code in the task has handle it.
Console.WriteLine()
Console.WriteLine("A Cancellable Task")
' Cancelling a Task
Dim cts As New Threading.CancellationTokenSource()
Dim ct = cts.Token
Dim myTask3 As New Task(Sub()
For x = 0 To 100
If ct.IsCancellationRequested Then Exit Sub
Console.Write(" {0}", x)
Thread.Sleep(100)
Next
End Sub, cts)
myTask3.Start()
Console.WriteLine("Press any key to Cancel")
Console.ReadKey()
Console.WriteLine("Cancelling")
' Note: We cancel the token source and not the token.
cts.Cancel()
Console.WriteLine("Cancelled")
' Wait for it to finish being cancelled.
myTask3.Wait()
Console.ReadKey()
End Sub
End Module
Parallel Tasks (TPL)
For this example we shall do a Matrix Multiply.
Module Module2
Sub Main()
Dim m1(,) As Integer = {{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6}}
Dim m2(,) As Integer = {{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6}}
Dim m3(5, 5) As Integer
Dim m4(5, 5) As Integer
Dim sw As New System.Diagnostics.Stopwatch
Console.WriteLine("Matrix Multiply")
PrintMatrix(m1)
Console.WriteLine("*")
PrintMatrix(m2)
Console.WriteLine("=")
sw.Start()
m3 = matrix_multiply_1(m1, m2)
sw.Stop()
PrintMatrix(m3)
Console.WriteLine("Took {0} ticks", sw.ElapsedTicks)
Console.WriteLine()
sw.Reset()
Console.WriteLine("Matrix Multiply (Parallel)")
PrintMatrix(m1)
Console.WriteLine("*")
PrintMatrix(m2)
Console.WriteLine("=")
sw.Start()
m4 = matrix_multiply_1(m1, m2)
m3 = matrix_multiply_1(m1, m2)
sw.Stop()
PrintMatrix(m4)
Console.WriteLine("Took {0} ticks", sw.ElapsedTicks)
Console.WriteLine()
End Sub
Sub PrintMatrix(ByRef m(,) As Integer)
Dim xl = m.GetUpperBound(0)
Dim yl = m.GetUpperBound(1)
Console.WriteLine("[")
For y = 0 To yl
For x = 0 To xl
If x = 0 Then
Console.Write(" [{0},", m(y, x))
ElseIf x = xl Then
Console.WriteLine("{0}]", m(y, x))
Else
Console.Write("{0},", m(y, x))
End If
Next
Next
Console.WriteLine("]")
End Sub
Function matrix_multiply_1(ByVal A As Integer(,), ByVal B As Integer(,))
Dim c(5, 5) As Integer
For i = 0 To 5
For j = 0 To 5
For k = 0 To 5
c(i, j) += A(i, k) * B(k, j)
Next
Next
Next
Return c
End Function
Function matrix_multiply_p(ByVal A As Integer(,), ByVal B As Integer(,))
Dim c(5, 5) As Integer
Parallel.For(0, 6,
Sub(i)
Parallel.For(0, 6,
Sub(j)
Parallel.For(0, 6,
Sub(k)
c(i, j) += A(i, k) * B(k, j)
End Sub)
End Sub)
End Sub)
Return c
End Function
End Module
Normal: 9000 ticks
Parallel: 337 ticks
The TPL is also utilise by PLINQ. Try inserting .AsParallel in to your LINQ.
This post has been edited by AdamSpeight2008: 18 March 2011 - 06:58 AM






MultiQuote






|