Page 1 of 1

Tasks (>= .net 4.0) Rate Topic: -----

#1 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2251
  • View blog
  • Posts: 9,433
  • Joined: 29-May 08

Posted 17 March 2011 - 03:52 PM

Tasks

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


Is This A Good Question/Topic? 4
  • +

Replies To: Tasks (>= .net 4.0)

#2 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4451
  • View blog
  • Posts: 7,752
  • Joined: 08-June 10

Posted 17 March 2011 - 08:47 PM

Awesome. I'll certainly be using these in future projects.
Was This Post Helpful? 0
  • +
  • -

#3 ???  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 48
  • Joined: 25-November 10

Posted 22 March 2011 - 04:44 PM

Wow!
I did not know that was possible. :blink:
Was This Post Helpful? 0
  • +
  • -

#4 bhorton  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 31-August 11

Posted 31 August 2011 - 02:00 PM

Ok ... I must have done something really wrong.

I created this in a console app and when I ran it, I got:

Normal: 620 ticks
Parallel: 30462 ticks

How could that be possible?
Was This Post Helpful? 0
  • +
  • -

#5 shadachi  Icon User is offline

  • D.I.C Head

Reputation: 15
  • View blog
  • Posts: 141
  • Joined: 25-January 08

Posted 26 July 2012 - 02:42 AM

            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)




Why are we multiplying two matrices and why is the function matrix_multiply_1 used for the parallel portion shouldn't it be matrix_multiply_p.

By running the Matrix_multiply_p , the parallel ticks that I've got is 12578 while the regular one is around 900. Any reason why ?

This post has been edited by shadachi: 26 July 2012 - 02:44 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1