SlideShare a Scribd company logo
Rainer Stropek | software architects gmbh


   Parallel & Async in C#
Agenda
Parallele und asynchrone Programmierung sind von einem Nischenthema
zu einer wichtigen Herausforderung für jeden .NET-Entwickler geworden.
Spätestens am Beispiel der Windows Runtime (WinRT), dem API für
Windows Store Apps, sieht man, welche Bedeutung dem Thema
beizumessen ist: In WinRT sind nahezu alle Funktionen, die etwas länger
dauern könnten, asynchron. Dadurch werden die vorhandenen
Ressourcen besser genutzt und das UI friert nie ein.

Rainer Stropek beginnt in seinem Workshop mit Grundlagen über parallele
und asynchrone Programmierung mit .NET. Er zeigt TPL und PLINQ in
Aktion. Darauf aufbauend geht er auf die neuen C#-Schlüsselwörter async
und await ein. Design-Guidelines für moderne, Task-basierende APIs sind
der Abschluss des Workshops. Sie erfahren, wie Task
Cancellation, Progress Reporting etc. richtig gemacht werden. Rainer stellt
zum Workshop ein Slidedeck zum Nachschlagen zur Verfügung, im
Workshop selbst stehen aber praktische Beispiele (C#) im Vordergrund.
Introduction
• software architects gmbh
• Rainer Stropek
   – Developer, Speaker, Trainer
   – MVP for Windows Azure
     since 2010
   – rainer@timecockpit.com
   –         @rstropek



                                   http://www.timecockpit.com
                                   http://www.timecockpit.com/devblog
Functional Programming
    Concepts In C#
       A Short Recap…
A short recap…
• Lambda expressions in C#
• Anonymous delegates
   – Func, Func<T>
   – Action, Action<T>
• Concepts of functional programming in C#
   – Use first-class functions to reduce duplication of code
• Application of functional programming in LINQ
• BTW – This has been around since
  C# 2 and/or 3.x
public delegate int MathOperation(int x, int y);

static void Main(string[] args)
{
   MathOperation delegateOperation = Add;

    // Anonymous delegate
    MathOperation anonymousDelegateOperation = delegate(int num1, int num2)
    {
       return num1 + num2;
    };

    // Func<T>
    Func<int, int, int> operationFunction = Add;

    // Simple lambda functions
    operationFunction = (x, y) => x + y;
    delegateOperation = (x, y) => x + y;
}

public static int Add(int num1, int num2)
{
   return num1 + num2;
}
public delegate string[] GenerateDataOperation(int numberOfElements);

static void Main(string[] args) {
   GenerateDataOperation generateOperation = NameGenerator;

    // Multi-line anonymous delegate
    GenerateDataOperation anonymousGenerateOperation =
       delegate(int numberOfElements) {
       var result = new string[numberOfElements];
       for (int i = 0; i < numberOfElements; i++) {
           result[i] = string.Format("line_{0}", i);
       }

         return result;
    };

    // Multi-line lambda functions
    Func<int, string[]>   generatorFunction = (numberOfElements) => {
           var result =   new string[numberOfElements];
           for (int i =   0; i < numberOfElements; i++) {
              result[i]   = string.Format("line_{0}", n);
           }

              return result;
         };
}
Do we need some recap on LINQ?

• IEnumerable<T>
  – Covariance
• C# LINQ syntax
• LINQ Support in .NET Framework
• Lambda expressions as data
  – IQueryable<T>
  – Expression trees
// Result of a method
var res5 = from training in demoData
           select training.Attendees.First();

// Result of a property
var res6 = from training in demoData              Map part of the famous
           select training.Duration;               map/reduce concept

// Anonymous type
var res7 = from training in demoData
           select new {                         Even if you do not like var,
             training.Title,                      here you have to use it
             NumberOfAttendees =
               training.Attendees.Count()
           };

// Instance of existing type
var res8 = from training in demoData
           select new TrainingInfo {
             Title = training.Title,
             NumberOfAttendees =
               training.Attendees.Count()
           };
Query vs. Method Syntax
• Linq queries are a concept of the language, not the .NET
  Framework
• Compiler converts query into method calls




                                                  Pass first-class function as
                                                 parameter to a LINQ method
public static void SelectManyDemo()
{
   var strings = new []
   {
      "This is string number one",
      "This might be a second string"      Method
   };                                      Syntax


    var result = strings
       .SelectMany(s => s.Split(' '))   Reduce
       .Distinct()
       .Select(s => s.ToLower())
       .OrderBy(s => s);
    foreach (var line in result)         Map
    {
       Console.WriteLine(line);
    }
}
var res12 = from training in demoData
                                             Method syntax
  group training                            embedded in LINQ
     by new { training.Title,                    query
       NumberOfAttendees =
         training.Attendees.Count(
           a => a.CountryOfOrigin == "AT")
     }
     into trainingGroup
  where trainingGroup.Key.NumberOfAttendees > 0
  select new { trainingGroup.Key.Title,
     AttendeesFromAustria =
       trainingGroup.Key.NumberOfAttendees
  };
Parallel Programming
      Task Parallel Library
Goals
• Understand Tasks  foundation for
  async/await
• Take a close look at C# 4.5‘s stars
  async/await
Recommended Reading
• Joseph Albahari, Threading in C#
  (from his O‘Reilly book C# 4.0 in a Nutshell)
• Patterns of Parallel Programming
• Task-based Asynchronous Pattern
• A technical introduction to the Async CTP
• Using Async for File Access
• Async Performance: Understanding the Costs
  of Async and Await (MSDN Magazine)
See also Patterns of Parallel Programming
Multithreading

Pre .NET 4            .NET 4
• System.Threading    • System.Threading.
  Namespace             Tasks Namespace
• Thread Klasse       • Task und
                        Task<TResult>
                        Klassen
• ThreadPool Klasse   • TaskFactory Klasse
                      • Parallel Klasse
Kurzer Überblick über Tasks
•   Starten
     –   Parallel.Invoke(…)                       Nicht in Silverlight 
     –   Task.Factory.StartNew(…)
•   Warten
     –   myTask.Wait()
     –   Task.WaitAll
     –   Task.WaitAny
     –   Task.Factory.ContinueWhenAll(…)
     –   Task.Factory.ContinueWhenAny(…)
•   Verknüpfen
     –   Task.Factory.StartNew(…,
         TaskCreationOptions.AttachedToParent);
•   Abbrechen
     –   Cancellation Tokens


                                                                           MSDN
Schleifen - Parallel.For
var source = new double[Program.Size];
var destination = new double[Program.Size];

Console.WriteLine(MeasuringTools.Measure(() => {
        for (int i = 0; i < Program.Size; i++) {
            source[i] = (double)i;
        }

       for (int i = 0; i < Program.Size; i++) {
           destination[i] = Math.Pow(source[i], 2);
       }
   }));

Console.WriteLine(MeasuringTools.Measure(() => {
        Parallel.For(0, Program.Size, (i) => source[i] = (double)i);
        Parallel.For(0, Program.Size,
            (i) => destination[i] = Math.Pow(source[i], 2));
    }));
Schleifen - Parallel.For
• Unterstützung für Exception Handling
• Break und Stop Operationen
   – Stop: Keine weiteren Iterationen
   – Break: Keine Iterationen nach dem aktuellen Index mehr
   – Siehe dazu auch ParallelLoopResult
• Int32 und Int64 Laufvariablen
• Konfigurationsmöglichkeiten (z.B. Anzahl an Threads)
• Schachtelbar
   – Geteilte Threading-Ressourcen
• Effizientes Load Balancing
                                                 Nicht selbst entwickeln!
• U.v.m.
Schleifen - Parallel.ForEach
Console.WriteLine(
    "Serieller Durchlauf mit foreach: {0}",
    MeasuringTools.Measure(() =>
    {
        double sumOfSquares = 0;
        foreach (var square in Enumerable.Range(0, Program.Size).Select(
            i => Math.Pow(i, 2)))
        {
            sumOfSquares += square;
        }
    }));
                                                        Hoher Aufwand für
Console.WriteLine(                                   abgesicherten Zugriff auf
    "Paralleler Durchlauf mit foreach: {0}",            MoveNext/Current
    MeasuringTools.Measure(() =>                       Parallele Version oft
    {                                                      langsamer
        double sumOfSquares = 0;
        Parallel.ForEach(Enumerable.Range(0, Program.Size)
            .Select(i => Math.Pow(i, 2)), square => sumOfSquares += square);
    }));
Von LINQ zu PLINQ
LINQ                  PLINQ
var result = source   var result = source
    .Where(…)             .AsParallel()
    .Select(…)            .Where(…)
                          .Select(…)


                         Aus IEnumerable wird
                           ParallelQuery




                       Tipp: AsOrdered() erhält die
                              Sortierreihenfolge
Performancetipps für PLINQ
•   Allokieren von Speicher in parallelem Lambdaausdruck vermeiden
     –   Sonst kann Speicher + GC zum Engpass werden
     –   Wenn am Server: Server GC
•   False Sharing vermeiden
•   Bei zu kurzen Delegates ist Koordinationsaufwand für Parallelisierung oft höher
    als Performancegewinn
     –    Expensive Delegates
     –   Generell: Auf richtige Granularität der Delegates achten
•   AsParallel() kann an jeder Stelle im LINQ Query stehen
     –    Teilweise serielle, teilweise parallele Ausführung möglich
•   Über Environment.ProcessorCount kann Anzahl an Kernen ermittelt
    werden
• Messen, Messen, Messen!
Was läuft hier falsch? (Code)
 var result = new List<double>();
 Console.WriteLine(
     "Paralleler Durchlauf mit Parallel.ForEach: {0}",
     MeasuringTools.Measure(() =>
     {
         Parallel.ForEach(                        Parallel.ForEach verwendet
             source.AsParallel(),               IEnumerable<T>  unnötige
             i =>                                        Merge-Schritte
             {
                 if (i % 2 == 0)
                 {
                     lock (result)
                     {
                         result.Add(i);
                     }
                 }
             });
     }));
Was läuft hier falsch? (Code)



                                        
 Console.WriteLine(
     "Paralleler Durchlauf mit Parallel.ForAll: {0}",
     MeasuringTools.Measure(() =>
     {
         source.AsParallel().ForAll(
             i =>
             {
                 if (i % 2 == 0)
                 {
                     lock (result)
                     {
                         result.Add(i);
                     }
                 }
             });
     }));




            Lock-free Collection wäre
                überlegenswert!
Was läuft hier falsch? (Code)
 Console.WriteLine(
     "Serielles Lesen: {0}",                      Optimal für Parallelisierung
     MeasuringTools.Measure(() =>              selbst bei einem Core (IO-Bound
     {                                                       Waits)
         foreach (var url in urls)
         {
             var request = WebRequest.Create(url);
             using (var response = request.GetResponse())
             {
                 using (var stream = response.GetResponseStream())
                 {
                     var content = new byte[1024];
                     while (stream.Read(content, 0, 1024) != 0) ;
                 }
             }
         }
     }));
Was läuft hier falsch? (Code)
 Console.WriteLine(                                 Anzahl Threads = Anzahl Cores;
     "Paralleles Lesen: {0}",
                                                     könnte mehr sein, da IO-Bound
     MeasuringTools.Measure(() =>
     {                                                           waits
         Parallel.ForEach(urls, url =>
         {
             var request = WebRequest.Create(url);
             using (var response = request.GetResponse())
             {
                 using (var stream = response.GetResponseStream())
                 {
                     var content = new byte[1024];
                     while (stream.Read(content, 0, 1024) != 0) ;
                 }
             }
         });
     }));

              Parallel.ForEach(
                urls,
                new ParallelOptions() { MaxDegreeOfParallelism = urls.Length },
                url => { … });
Was läuft hier falsch? (Code)
 Console.WriteLine(




                                                           
     "Paralleles Lesen: {0}",
     MeasuringTools.Measure(() =>
     {
         urls.AsParallel().WithDegreeOfParallelism(urls.Length)
             .Select(url => WebRequest.Create(url))
             .Select(request => request.GetResponse())
             .Select(response => new {
                 Response = response,
                 Stream = response.GetResponseStream() })
             .ForAll(stream =>
                 {
                     var content = new byte[1024];
                     while (stream.Stream.Read(content, 0, 1024) != 0) ;
                     stream.Stream.Dispose();
                     stream.Response.Close();
                 });
     }));


                                                OK für Client, tödlich für Server!
                                          Wenn Anzahl gleichzeitiger User wichtig ist sind
                                                andere Lösungen vorzuziehen.
private static void DoSomething()
{
   Action<Action> measure = (body) =>
   {
      var startTime = DateTime.Now;
      body();
      Console.WriteLine("{0} {1}",
         Thread.CurrentThread.ManagedThreadId,                 This process will run in
         DateTime.Now - startTime);                                    parallel
   };

    Action calcProcess = () =>
       { for (int i = 0; i < 100000000; i++);};

    measure(() =>
       Task.WaitAll(Enumerable.Range(0, 10)
          .Select(i => Task.Run(() => measure(calcProcess)))
          .ToArray()));
}
                            Note that we use the new Task.Run
                          function here; previously you had to use
                                Task.Factory.StartNew
Action<Action> measure = (body) => {
    var startTime = DateTime.Now;
    body();
    Console.WriteLine("{0} {1}",
      Thread.CurrentThread.ManagedThreadId,
      DateTime.Now - startTime);
};

Action calcProcess = () =>
   { for (int i = 0; i < 350000000; i++);};
Action ioProcess = () =>
   { Thread.Sleep(1000); };                     Note that this task is not
                                                    compute-bound
// ThreadPool.SetMinThreads(5, 5);
measure(() =>{
    Task.WaitAll(Enumerable.Range(0, 10)
        .Select(i => Task.Run(() => measure(ioProcess)))
        .ToArray());
});
Action<Action> measure = (body) =>{
   var startTime = DateTime.Now;
   body();
   Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId,
                     DateTime.Now - startTime);
};

Action calcProcess = () => { for (int i = 0; i < 350000000; i++);};
Action ioProcess = () => { Thread.Sleep(1000); };

ThreadPool.SetMinThreads(5, 5);
measure(() => Enumerable.Range(0, 10)
   .AsParallel()
   .WithDegreeOfParallelism(5)
   .ForAll(i => measure(ioProcess)));
Excursus - PLINQ
• Use .AsParallel to execute LINQ
  query in parallel
• Be careful if you care about ordering
  – Use .AsOrdered if necessary
• Use .WithDegreeOfParallelism in
  case of IO-bound tasks
• Use .WithCancellation to enable
  cancelling
private static void DoSomethingElse()
{
   Func<int, int> longRunningFunc = (prevResult) =>
      {
         Thread.Sleep(1000);
         return prevResult + 42;
      };


Concat tasks using ContinueWith




    var task = Task.Run(() => longRunningFunc(0))
       .ContinueWith(t => longRunningFunc(t.Result))
       .ContinueWith(t => longRunningFunc(t.Result));
    task.Wait();
    Console.WriteLine(task.Result);
}                                          Wait for completion of a
                                                     task.
Exception Handling
• AggregateException
• Remove nested Aggregate Exceptions with
  Flatten
• Use CancellationToken for cooperative
  cancellation
• Use the Handle method instead of loop over
  Aggregate Exceptions
• Use Task.Exception
var task1 = Task.Factory.StartNew(() =>
{
    throw new MyCustomException("I'm bad, but not too bad!");
});

try
{
      task1.Wait();
}
catch (AggregateException ae)
{
    // Assume we know what's going on with this particular exception.
    // Rethrow anything else. AggregateException.Handle provides
    // another way to express this. See later example.
    foreach (var e in ae.InnerExceptions)
    {
        if (e is MyCustomException)
        {
            Console.WriteLine(e.Message);
        }
        else
        {
            throw;
        }
    }

}
var task1 = Task.Factory.StartNew(() =>
{
    var child1 = Task.Factory.StartNew(() => {
            var child2 = Task.Factory.StartNew(() => {
                throw new MyCustomException("Attached child2 faulted.");
            },
            TaskCreationOptions.AttachedToParent);

            // Uncomment this line to see the exception rethrown.
            // throw new MyCustomException("Attached child1 faulted.");
        },
        TaskCreationOptions.AttachedToParent);
});

try {
    task1.Wait();
}
catch (AggregateException ae) {

     foreach (var e in ae.Flatten().InnerExceptions)
     {
        …
     }
     // or ...
    // ae.Flatten().Handle((ex) => ex is MyCustomException);

}
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;

var task1 = Task.Factory.StartNew(() =>
{
    CancellationToken ct = token;
    while (someCondition)
    {
        // Do some work...
        Thread.SpinWait(50000);
        ct.ThrowIfCancellationRequested();
    }
},
token);

// No waiting required.
foreach (var e in ae.InnerExceptions)
{
    if (e is MyCustomException)
    {
        Console.WriteLine(e.Message);
    }
    else
    {
        throw;
    }
}




ae.Handle((ex) =>
{
    return ex is MyCustomException;
});
var task1 = Task.Factory.StartNew(() =>
{
    throw new MyCustomException("Task1 faulted.");
})
.ContinueWith((t) =>
    {
        Console.WriteLine("I have observed a {0}",
            t.Exception.InnerException.GetType().Name);
    },
    TaskContinuationOptions.OnlyOnFaulted);
Thread Synchronisation
• Use C# lock statement to control access to
  shared variables
  – Under the hoods Monitor.Enter and
    Monitor.Exit is used
  – Quite fast, usually fast enough
  – Only care for lock-free algorithms if really
    necessary
• Note that a thread can lock the same object in
  a nested fashion
// Source: C# 4.0 in a Nutshell, O‘Reilly Media
class ThreadSafe
{
  static readonly object _locker = new object();
  static int _val1, _val2;

    static void Go()
    {
      lock (_locker)
      {
        if (_val2 != 0) Console.WriteLine (_val1 / _val2);
        _val2 = 0;
      }
    }
}

// This is what happens behind the scenes
bool lockTaken = false;
try
{
  Monitor.Enter(_locker, ref lockTaken);
  // Do your stuff...
}
finally
{
    if (lockTaken) Monitor.Exit(_locker);
}
// Provide a factory for instances of the Random class per thread
var tlr = new ThreadLocal<Random>(
   () => new Random(Guid.NewGuid().GetHashCode()));

var watch = Stopwatch.StartNew();

var tasks =
   // Run 10 tasks in parallel
   Enumerable.Range(0, 10)
       .Select(_ => Task.Run(() =>
          // Create a lot of randoms between 0 and 9 and calculate
          // the sum
          Enumerable.Range(0, 1000000)
              .Select(__ => tlr.Value.Next(10))
              .Sum()))
       .ToArray();
Task.WaitAll(tasks);

// Calculate the total
Console.WriteLine(tasks.Aggregate<Task<int>, int>(
   0, (agg, val) => agg + val.Result));

Console.WriteLine(watch.Elapsed);
                                                     Do you think this is a good
watch = Stopwatch.StartNew();                                solution?
// Provide a factory for instances of the Random class per thread
var tlr = new ThreadLocal<Random>(
   () => new Random(Guid.NewGuid().GetHashCode()));

var watch = Stopwatch.StartNew();

Console.WriteLine(
   ParallelEnumerable.Range(0, 10000000)
       .Select(_ => tlr.Value.Next(10))
       .Sum());

Console.WriteLine(watch.Elapsed);




                                                  Prefer PLINQ over TPL because it
                                                  automatically breaks the workload
                                                           into packages.
Alternatives For lock
• Mutex
• Semaphore(Slim)
• ReaderWriterLock(Slim)
• Not covered here in details
Thread Synchronization
• AutoResetEvent
   – Unblocks a thread once when it receives a signal from another
     thread
• ManualResetEvent(Slim)
   – Like a door, opens and closes again
• CountdownEvent
   – New in .NET 4
   – Unblocks if a certain number of signals have been received
• Barrier class
   – New in .NET 4
   – Not covered here
• Wait and Pulse
   – Not covered here
Producer/Consumer
       Was läuft hier falsch? (Code)
var buffer = new Queue<long>();
var cancelTokenSource = new CancellationTokenSource();
var done = false;

var producer = Task.Factory.StartNew((cancelTokenObj) => {
        var counter = 10000000;
        var cancelToken = (CancellationToken)cancelTokenObj;
        try {
            while (!cancelToken.IsCancellationRequested && counter-- > 0) {
                // Here we get some data (e.g. reading it from a file)
                var value = DateTime.Now.Ticks;
                // Write it to buffer with values that have to be processed
                buffer.Enqueue(value);
            }
        }
        finally {
            done = true;
        }                                     buffer wird nicht gelockt
    }, cancelTokenSource.Token);
Producer/Consumer
       Was läuft hier falsch? (Code)

var consumer = Task.Factory.StartNew((cancelTokenObj) =>
    {
       var cancelToken = (CancellationToken)cancelTokenObj;
       while (!cancelToken.IsCancellationRequested && !done)
       {
           // Get the next value to process
           lock (buffer)
           {                                             Prüfung   ob leer fehlt
               var value = buffer.Dequeue();
           }

          // Here we do some expensive procesing
          Thread.SpinWait(1000);
       }
   }, cancelTokenSource.Token);
                                           Consumer ist viel langsamer als
                                                Producer  Producer
                                         überschwemmt Consumer mit Daten
Collections für parallele
               Programmierung
• System.Collections.Concurrent für Thread-
  Safe Collections
   – BlockingCollection<T>
     Blocking und Bounding-Funktionen
   – ConcurrentDictionary<T>
   – ConcurrentQueue<T>
   – ConcurrentStack<T>
   – ConcurrentBag<T>
• Optimal zur Umsetzung von Pipelines
   – Datei wird gelesen, gepackt, verschlüsselt, geschrieben
Producer/Consumer
       Was läuft hier falsch? (Code)
var buffer = new BlockingCollection<long>(10);
var cancelTokenSource = new CancellationTokenSource();

var producer = Task.Factory.StartNew((cancelTokenObj) => {
    var counter = 10000000;
    var cancelToken = (CancellationToken)cancelTokenObj;
    try     {
        while (!cancelToken.IsCancellationRequested && counter-- > 0) {
            // Here we get some data (e.g. reading it from a file)
            var value = DateTime.Now.Ticks;
            // Write it to the buffer with values that have to be processed
            buffer.Add(value);
        }




                                                         
    }
    finally {
        buffer.CompleteAdding();
    }
}, cancelTokenSource.Token);
Producer/Consumer
       Was läuft hier falsch? (Code)

var consumer = Task.Factory.StartNew((cancelTokenObj) =>
{
    var cancelToken = (CancellationToken)cancelTokenObj;
    foreach (var value in buffer.GetConsumingEnumerable())
    {
        if ( cancelToken.IsCancellationRequested )
        {
            break;
        }




                                                
       // Here we do some expensive procesing
       Thread.SpinWait(1000);
    }
}, cancelTokenSource.Token);
Async Programming
    The big new thing in C# 5
private static void DownloadSomeTextSync()
{
   using (var client = new WebClient())
   {
      Console.WriteLine(
         client.DownloadString(new Uri(string.Format(
            "http://{0}",
            (Dns.GetHostAddresses("www.basta.net"))[0]))));
   }
}



                                        Synchronous version of the code;
                                             would block UI thread
private static void DownloadSomeText()
{
   var finishedEvent = new AutoResetEvent(false);

    // Notice the IAsyncResult-pattern here
    Dns.BeginGetHostAddresses("www.basta.net", GetHostEntryFinished,
       finishedEvent);
    finishedEvent.WaitOne();
}

private static void GetHostEntryFinished(IAsyncResult result)
{
   var hostEntry = Dns.EndGetHostAddresses(result);
   using (var client = new WebClient())
   {
       // Notice the Event-based asynchronous pattern here
       client.DownloadStringCompleted += (s, e) =>
       {
          Console.WriteLine(e.Result);
          ((AutoResetEvent)result.AsyncState).Set();
       };
       client.DownloadStringAsync(new Uri(string.Format(
          "http://{0}",
          hostEntry[0].ToString())));
   }                                               Notice that control flow is not clear
}                                                               any more.
private static void DownloadSomeText()
{
   var finishedEvent = new AutoResetEvent(false);

    // Notice the IAsyncResult-pattern here
    Dns.BeginGetHostAddresses(
       "www.basta.net",
       (result) =>
       {
           var hostEntry = Dns.EndGetHostAddresses(result);
           using (var client = new WebClient())
           {
              // Notice the Event-based asynchronous pattern here
              client.DownloadStringCompleted += (s, e) =>
              {
                  Console.WriteLine(e.Result);
                  ((AutoResetEvent)result.AsyncState).Set();
              };
              client.DownloadStringAsync(new Uri(string.Format(
                  "http://{0}",
                  hostEntry[0].ToString())));
           }
       },
       finishedEvent);
    finishedEvent.WaitOne();                         Notice how lambda expression
}                                                     can make control flow clearer
Notice the use of the new
                                                         Task Async Pattern APIs in
                                                               .NET 4.5 here
private static void DownloadSomeTextUsingTask()
{
   Dns.GetHostAddressesAsync("www.basta.net")
       .ContinueWith(t =>
       {
          using (var client = new WebClient())
          {
              return client.DownloadStringTaskAsync(new Uri(string.Format(
                     "http://{0}",
                     t.Result[0].ToString())));
          }
       })
       .ContinueWith(t2 => Console.WriteLine(t2.Unwrap().Result))
       .Wait();
}



                         Notice the use of lambda       Notice how code has become
                     expressions all over the methods    shorter and more readable
Rules For Async Method Signatures
• Method name ends with Async
• Return value
  – Task if sync version has return type void
  – Task<T> if sync version has return type T
• Avoid out and ref parameters
  – Use e.g. Task<Tuple<T1, T2, …>> instead
// Synchronous version
private static void DownloadSomeTextSync()
{
   using (var client = new WebClient())
   {
       Console.WriteLine(
          client.DownloadString(new Uri(string.Format(
              "http://{0}",
              (Dns.GetHostAddresses("www.basta.net"))[0]))));
   }
}
                                                    Notice how similar the sync and
                                                          async versions are!


// Asynchronous version
private static async void DownloadSomeTextUsingTaskAsync()
{
   using (var client = new WebClient())
   {
       Console.WriteLine(
          await client.DownloadStringTaskAsync(new Uri(string.Format(
              "http://{0}",
              (await Dns.GetHostAddressesAsync("www.basta.net"))[0]))));
   }
}
private static async void DownloadSomeTextUsingTaskAsync2()
   {
      using (var client = new WebClient())
      {
          try
          {
              var ipAddress = await Dns.GetHostAddressesAsync("www.basta.net");
              var content = await client.DownloadStringTaskAsync(
                 new Uri(string.Format("htt://{0}", ipAddress[0])));
              Console.WriteLine(content);
          }
          catch (Exception)
          {
              Console.WriteLine("Exception!");
          }
      }
   }




  Let’s check the
generated code and
 debug the async
        code
Guidelines for async/await
• If Task ended in Canceled
  state, OperationCanceledExceptio
  n will be thrown
private async static void CancelTask()
{
   try
   {
       var cancelSource = new CancellationTokenSource();
       var result = await DoSomethingCancelledAsync(cancelSource.Token);
       Console.WriteLine(result);
   }
   catch (OperationCanceledException)
   {
       Console.WriteLine("Cancelled!");
   }
}

private static Task<int> DoSomethingCancelledAsync(CancellationToken token)
{
   // For demo purposes we ignore token and always return a cancelled task
   var result = new TaskCompletionSource<int>();
   result.SetCanceled();
   return result.Task;
}
                                                        Note usage of
                                                TaskCompletionSource<T> here
Note that async API of WebClient uses
  existing cancellation logic instead of
    CancellationTokenSource
Parallel and Async Programming With C#
Guidelines for async/await
• Caller runs in parallel to awaited
  methods
• Async methods sometimes do not run
  async (e.g. if task is already completed
  when async is reached)
Guidelines for async/await (UI Layer)

• async/await use SynchronizationContext to execute the
  awaiting method  UI thread in case of UI layer
• Use Task.ConfigureAwait to disable this behavior
   – E.g. inside library to enhance performance
public partial class MainWindow : Window
{
public MainWindow()
{
   this.DataContext = this;
   this.ListBoxContent = new ObservableCollection<string>();
   this.InitializeComponent();
   this.ListBoxContent.Add("Started");

    this.Loaded += async (s, e) =>
       {
           for (int i = 0; i < 10; i++)
           {
              ListBoxContent.Add(await Task.Run(() =>
                  {
                     Thread.Sleep(1000);
                     return "Hello World!";
                  }));
           }

            this.ListBoxContent.Add("Finished");
       };
}

public ObservableCollection<string> ListBoxContent { get; private set; }
Parallel and Async Programming With C#
Guidelines For Implementing
 Methods Ready For async/await
• Return Task/Task<T>
• Use postfix Async
• If method support cancelling, add parameter of type
  System.Threading.CancellationToken
• If method support progress reporting, add
  IProgress<T> parameter
• Only perform very limited work before returning to the
  caller (e.g. check arguments)
• Directly throw exception only in case of usage errors
public class Program : IProgress<int>
{
   static void Main(string[] args)
   {
       var finished = new AutoResetEvent(false);
       PerformCalculation(finished);
       finished.WaitOne();
   }

   private static async void PerformCalculation(AutoResetEvent finished)
   {
      Console.WriteLine(await CalculateValueAsync(
          42,
          CancellationToken.None,
          new Program()));
      finished.Set();
   }

   public void Report(int value)
   {
      Console.WriteLine("Progress: {0}", value);
   }
private static Task<int> CalculateValueAsync(
        int startingValue,
        CancellationToken cancellationToken,
        IProgress<int> progress)
    {
        if (startingValue < 0)
        {
            // Usage error
            throw new ArgumentOutOfRangeException("startingValue");
        }

        return Task.Run(() =>
            {
               int result = startingValue;
               for (int outer = 0; outer < 10; outer++)
               {
                   cancellationToken.ThrowIfCancellationRequested();

                     // Do some calculation
                     Thread.Sleep(500);
                     result += 42;

                     progress.Report(outer + 1);
                 }

                 return result;
           });                                       Note that this pattern is good for
    }                                                      compute-bound jobs
}
private static async void PerformCalculation(AutoResetEvent finished)
{
   try
   {
       var cts = new CancellationTokenSource();
       Task.Run(() =>
          {
              Thread.Sleep(3000);
              cts.Cancel();
          });
       var result = await CalculateValueAsync(
          42,
          cts.Token,
          new Program());
   }
   catch (OperationCanceledException)
   {
       Console.WriteLine("Cancelled!");
   }

    finished.Set();
}
                                                 Note cancellation and handling of
                                                OperationCanceledException.
private static Task<int> CalculateValueAsync(
   int startingValue,
   CancellationToken cancellationToken,
   IProgress<int> progress)
{
   if (startingValue < 0)
   {
       // By definition the result has to be 0 if startingValue < 0
       return Task.FromResult(0);
   }

    return Task.Run(() =>
       {
           […]
       });
}


                    Note that you could use    Note how Task.FromResult is used
                TaskCompletionSource instead          to return a pseudo-task
Was läuft hier falsch? (Code)
 Console.WriteLine(
     "Paralleles Lesen mit TaskFactory: {0}",
     MeasuringTools.Measure(() =>
         {
            var tasks = new Task[urls.Length];
            for (int i = 0; i < urls.Length; i++)
            {
                tasks[i] = Task.Factory.StartNew(() => ReadUrl(urls[i]));
            }

               Task.WaitAll(tasks);
           }
     ));
 …                                            Delegate verwendet Wert von i
                                                aus dem Main Thread 
 private static void ReadUrl(object url)
                                             IndexOutOfRangeException
 {
     …
 }
Was läuft hier falsch? (Code)
 // Variante 1
 …                                             Durch lokale Variable wird delegate
 var tasks = new Task[urls.Length];          unabhängig; mehr zum Thema unter dem
 for (int i = 0; i < urls.Length; i++)                Schlagwort Closures
 {
     var tmp = i;
     tasks[i] = Task.Factory.StartNew(() => ReadUrl(urls[tmp]));
 }
 …



 // Variante 2
 var tasks = new Task[urls.Length];          State object wird an delegate übergeben
 for (int i = 0; i < urls.Length; i++)
 {
     tasks[i] = Task.Factory.StartNew(ReadUrl, urls[i]);
 }
for (var i = 0; i < 10; i++)
{
   new Thread(() => Console.Write(i)).Start();
                                                    You have to be careful
}
                                                      with closures and
                                                       multi-threading.
for (var i = 0; i < 10; i++)
{
   var temp = i;
   new Thread(() => Console.Write(temp)).Start();
}
// Setup timer using an action (notice the closure here)
var startTime = DateTime.Now;
using (var timer = new System.Threading.Timer(
   _ => progressIndicator(DateTime.Now - startTime), null, 1000, 1000))
{
   Thread.Sleep(3100);
}
F&A
Danke für die Teilnahme!
is the leading time tracking solution for knowledge
workers. Graphical time tracking calendar, automatic tracking of
your work using signal trackers, high level of extensibility and
customizability, full support to work offline, and SaaS
deployment model make it the optimal choice especially in the
IT consulting business.

Try                 for free and without any risk. You can get your
trial account at http://www.timecockpit.com. After the trial
period you can use                  for only 0,20€ per user and
month without a minimal subscription time and without a
minimal number of users.
ist die führende Projektzeiterfassung für
Knowledge Worker. Grafischer
Zeitbuchungskalender, automatische Tätigkeitsaufzeichnung
über Signal Tracker, umfassende Erweiterbarkeit und
Anpassbarkeit, volle Offlinefähigkeit und einfachste
Verwendung durch SaaS machen es zur Optimalen Lösung auch
speziell im IT-Umfeld.

Probieren Sie              kostenlos und ohne Risko einfach
aus. Einen Testzugang erhalten Sie unter http://www.timecockpit.com.
Danach nutzen Sie               um nur 0,20€ pro Benutzer und
Tag ohne Mindestdauer und ohne Mindestbenutzeranzahl.

More Related Content

What's hot

ExtJs Basic Part-1
ExtJs Basic Part-1ExtJs Basic Part-1
ExtJs Basic Part-1
Mindfire Solutions
 
Advance Java Programs skeleton
Advance Java Programs skeletonAdvance Java Programs skeleton
Advance Java Programs skeleton
Iram Ramrajkar
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescript
Katy Slemon
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
Visual Engineering
 
PHP 7 Crash Course
PHP 7 Crash CoursePHP 7 Crash Course
PHP 7 Crash Course
Colin O'Dell
 
Spring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffSpring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard Wolff
JAX London
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
Codemotion
 
Why Spring <3 Kotlin
Why Spring <3 KotlinWhy Spring <3 Kotlin
Why Spring <3 Kotlin
VMware Tanzu
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
Jeff Smith
 
C++ Functions
C++ FunctionsC++ Functions
C++ Functions
Jari Abbas
 
55 New Features in Java 7
55 New Features in Java 755 New Features in Java 7
55 New Features in Java 7
Boulder Java User's Group
 
ES6 metaprogramming unleashed
ES6 metaprogramming unleashedES6 metaprogramming unleashed
ES6 metaprogramming unleashed
Javier Arias Losada
 
Reactive Programming with JavaScript
Reactive Programming with JavaScriptReactive Programming with JavaScript
Reactive Programming with JavaScript
Codemotion
 
Open erp technical_memento_v0.6.3_a4
Open erp technical_memento_v0.6.3_a4Open erp technical_memento_v0.6.3_a4
Open erp technical_memento_v0.6.3_a4
openerpwiki
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
ciklum_ods
 
Exploring Angular 2 - Episode 1
Exploring Angular 2 - Episode 1Exploring Angular 2 - Episode 1
Exploring Angular 2 - Episode 1
Ahmed Moawad
 
CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013
Spyros Ioakeimidis
 
Codegeneration With Xtend
Codegeneration With XtendCodegeneration With Xtend
Codegeneration With Xtend
Sven Efftinge
 
Functional JavaScript Fundamentals
Functional JavaScript FundamentalsFunctional JavaScript Fundamentals
Functional JavaScript Fundamentals
Srdjan Strbanovic
 
Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4
ICS
 

What's hot (20)

ExtJs Basic Part-1
ExtJs Basic Part-1ExtJs Basic Part-1
ExtJs Basic Part-1
 
Advance Java Programs skeleton
Advance Java Programs skeletonAdvance Java Programs skeleton
Advance Java Programs skeleton
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescript
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
 
PHP 7 Crash Course
PHP 7 Crash CoursePHP 7 Crash Course
PHP 7 Crash Course
 
Spring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffSpring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard Wolff
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Why Spring <3 Kotlin
Why Spring <3 KotlinWhy Spring <3 Kotlin
Why Spring <3 Kotlin
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
C++ Functions
C++ FunctionsC++ Functions
C++ Functions
 
55 New Features in Java 7
55 New Features in Java 755 New Features in Java 7
55 New Features in Java 7
 
ES6 metaprogramming unleashed
ES6 metaprogramming unleashedES6 metaprogramming unleashed
ES6 metaprogramming unleashed
 
Reactive Programming with JavaScript
Reactive Programming with JavaScriptReactive Programming with JavaScript
Reactive Programming with JavaScript
 
Open erp technical_memento_v0.6.3_a4
Open erp technical_memento_v0.6.3_a4Open erp technical_memento_v0.6.3_a4
Open erp technical_memento_v0.6.3_a4
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
 
Exploring Angular 2 - Episode 1
Exploring Angular 2 - Episode 1Exploring Angular 2 - Episode 1
Exploring Angular 2 - Episode 1
 
CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013
 
Codegeneration With Xtend
Codegeneration With XtendCodegeneration With Xtend
Codegeneration With Xtend
 
Functional JavaScript Fundamentals
Functional JavaScript FundamentalsFunctional JavaScript Fundamentals
Functional JavaScript Fundamentals
 
Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4
 

Similar to Parallel and Async Programming With C#

The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)
jeffz
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
jeffz
 
LINQ Inside
LINQ InsideLINQ Inside
LINQ Inside
jeffz
 
What’s new in .NET
What’s new in .NETWhat’s new in .NET
What’s new in .NET
Doommaker
 
02basics
02basics02basics
02basics
Waheed Warraich
 
An Overview Of Python With Functional Programming
An Overview Of Python With Functional ProgrammingAn Overview Of Python With Functional Programming
An Overview Of Python With Functional Programming
Adam Getchell
 
New Functional Features of Java 8
New Functional Features of Java 8New Functional Features of Java 8
New Functional Features of Java 8
franciscoortin
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot Net
Neeraj Kaushik
 
Java findamentals1
Java findamentals1Java findamentals1
Java findamentals1
Todor Kolev
 
Java findamentals1
Java findamentals1Java findamentals1
Java findamentals1
Todor Kolev
 
Java findamentals1
Java findamentals1Java findamentals1
Java findamentals1
Todor Kolev
 
The Swift Compiler and Standard Library
The Swift Compiler and Standard LibraryThe Swift Compiler and Standard Library
The Swift Compiler and Standard Library
Santosh Rajan
 
.Net Multithreading and Parallelization
.Net Multithreading and Parallelization.Net Multithreading and Parallelization
.Net Multithreading and Parallelization
Dmitri Nesteruk
 
History of asynchronous in .NET
History of asynchronous in .NETHistory of asynchronous in .NET
History of asynchronous in .NET
Marcin Tyborowski
 
Programming in java basics
Programming in java  basicsProgramming in java  basics
Programming in java basics
LovelitJose
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
Van Huong
 
Java 8
Java 8Java 8
Java 8
Raghda Salah
 
Node js
Node jsNode js
Node js
hazzaz
 
02 functions, variables, basic input and output of c++
02   functions, variables, basic input and output of c++02   functions, variables, basic input and output of c++
02 functions, variables, basic input and output of c++
Manzoor ALam
 
Rx workshop
Rx workshopRx workshop
Rx workshop
Ryan Riley
 

Similar to Parallel and Async Programming With C# (20)

The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
 
LINQ Inside
LINQ InsideLINQ Inside
LINQ Inside
 
What’s new in .NET
What’s new in .NETWhat’s new in .NET
What’s new in .NET
 
02basics
02basics02basics
02basics
 
An Overview Of Python With Functional Programming
An Overview Of Python With Functional ProgrammingAn Overview Of Python With Functional Programming
An Overview Of Python With Functional Programming
 
New Functional Features of Java 8
New Functional Features of Java 8New Functional Features of Java 8
New Functional Features of Java 8
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot Net
 
Java findamentals1
Java findamentals1Java findamentals1
Java findamentals1
 
Java findamentals1
Java findamentals1Java findamentals1
Java findamentals1
 
Java findamentals1
Java findamentals1Java findamentals1
Java findamentals1
 
The Swift Compiler and Standard Library
The Swift Compiler and Standard LibraryThe Swift Compiler and Standard Library
The Swift Compiler and Standard Library
 
.Net Multithreading and Parallelization
.Net Multithreading and Parallelization.Net Multithreading and Parallelization
.Net Multithreading and Parallelization
 
History of asynchronous in .NET
History of asynchronous in .NETHistory of asynchronous in .NET
History of asynchronous in .NET
 
Programming in java basics
Programming in java  basicsProgramming in java  basics
Programming in java basics
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
Java 8
Java 8Java 8
Java 8
 
Node js
Node jsNode js
Node js
 
02 functions, variables, basic input and output of c++
02   functions, variables, basic input and output of c++02   functions, variables, basic input and output of c++
02 functions, variables, basic input and output of c++
 
Rx workshop
Rx workshopRx workshop
Rx workshop
 

Recently uploaded

Zaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdfZaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdf
AmandaCheung15
 
Step-By-Step Process to Develop a Mobile App From Scratch
Step-By-Step Process to Develop a Mobile App From ScratchStep-By-Step Process to Develop a Mobile App From Scratch
Step-By-Step Process to Develop a Mobile App From Scratch
softsuave
 
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
aslasdfmkhan4750
 
Mastering OnlyFans Clone App Development: Key Strategies for Success
Mastering OnlyFans Clone App Development: Key Strategies for SuccessMastering OnlyFans Clone App Development: Key Strategies for Success
Mastering OnlyFans Clone App Development: Key Strategies for Success
David Wilson
 
Russian Girls Call Navi Mumbai 🎈🔥9920725232 🔥💋🎈 Provide Best And Top Girl Ser...
Russian Girls Call Navi Mumbai 🎈🔥9920725232 🔥💋🎈 Provide Best And Top Girl Ser...Russian Girls Call Navi Mumbai 🎈🔥9920725232 🔥💋🎈 Provide Best And Top Girl Ser...
Russian Girls Call Navi Mumbai 🎈🔥9920725232 🔥💋🎈 Provide Best And Top Girl Ser...
bellared2
 
Using LLM Agents with Llama 3, LangGraph and Milvus
Using LLM Agents with Llama 3, LangGraph and MilvusUsing LLM Agents with Llama 3, LangGraph and Milvus
Using LLM Agents with Llama 3, LangGraph and Milvus
Zilliz
 
Integrating Kafka with MuleSoft 4 and usecase
Integrating Kafka with MuleSoft 4 and usecaseIntegrating Kafka with MuleSoft 4 and usecase
Integrating Kafka with MuleSoft 4 and usecase
shyamraj55
 
(CISOPlatform Summit & SACON 2024) Gen AI & Deepfake In Overall Security.pdf
(CISOPlatform Summit & SACON 2024) Gen AI & Deepfake In Overall Security.pdf(CISOPlatform Summit & SACON 2024) Gen AI & Deepfake In Overall Security.pdf
(CISOPlatform Summit & SACON 2024) Gen AI & Deepfake In Overall Security.pdf
Priyanka Aash
 
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
alexjohnson7307
 
Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024
Nicolás Lopéz
 
Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
Matthias Neugebauer
 
Tailored CRM Software Development for Enhanced Customer Insights
Tailored CRM Software Development for Enhanced Customer InsightsTailored CRM Software Development for Enhanced Customer Insights
Tailored CRM Software Development for Enhanced Customer Insights
SynapseIndia
 
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
shanihomely
 
(CISOPlatform Summit & SACON 2024) Regulation & Response In Banks.pdf
(CISOPlatform Summit & SACON 2024) Regulation & Response In Banks.pdf(CISOPlatform Summit & SACON 2024) Regulation & Response In Banks.pdf
(CISOPlatform Summit & SACON 2024) Regulation & Response In Banks.pdf
Priyanka Aash
 
Vulnerability Management: A Comprehensive Overview
Vulnerability Management: A Comprehensive OverviewVulnerability Management: A Comprehensive Overview
Vulnerability Management: A Comprehensive Overview
Steven Carlson
 
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
bhumivarma35300
 
The Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF GuideThe Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF Guide
Shiv Technolabs
 
Mule Experience Hub and Release Channel with Java 17
Mule Experience Hub and Release Channel with Java 17Mule Experience Hub and Release Channel with Java 17
Mule Experience Hub and Release Channel with Java 17
Bhajan Mehta
 
Evolution of iPaaS - simplify IT workloads to provide a unified view of data...
Evolution of iPaaS - simplify IT workloads to provide a unified view of  data...Evolution of iPaaS - simplify IT workloads to provide a unified view of  data...
Evolution of iPaaS - simplify IT workloads to provide a unified view of data...
Torry Harris
 
Types of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technologyTypes of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technology
ldtexsolbl
 

Recently uploaded (20)

Zaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdfZaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdf
 
Step-By-Step Process to Develop a Mobile App From Scratch
Step-By-Step Process to Develop a Mobile App From ScratchStep-By-Step Process to Develop a Mobile App From Scratch
Step-By-Step Process to Develop a Mobile App From Scratch
 
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
High Profile Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class ...
 
Mastering OnlyFans Clone App Development: Key Strategies for Success
Mastering OnlyFans Clone App Development: Key Strategies for SuccessMastering OnlyFans Clone App Development: Key Strategies for Success
Mastering OnlyFans Clone App Development: Key Strategies for Success
 
Russian Girls Call Navi Mumbai 🎈🔥9920725232 🔥💋🎈 Provide Best And Top Girl Ser...
Russian Girls Call Navi Mumbai 🎈🔥9920725232 🔥💋🎈 Provide Best And Top Girl Ser...Russian Girls Call Navi Mumbai 🎈🔥9920725232 🔥💋🎈 Provide Best And Top Girl Ser...
Russian Girls Call Navi Mumbai 🎈🔥9920725232 🔥💋🎈 Provide Best And Top Girl Ser...
 
Using LLM Agents with Llama 3, LangGraph and Milvus
Using LLM Agents with Llama 3, LangGraph and MilvusUsing LLM Agents with Llama 3, LangGraph and Milvus
Using LLM Agents with Llama 3, LangGraph and Milvus
 
Integrating Kafka with MuleSoft 4 and usecase
Integrating Kafka with MuleSoft 4 and usecaseIntegrating Kafka with MuleSoft 4 and usecase
Integrating Kafka with MuleSoft 4 and usecase
 
(CISOPlatform Summit & SACON 2024) Gen AI & Deepfake In Overall Security.pdf
(CISOPlatform Summit & SACON 2024) Gen AI & Deepfake In Overall Security.pdf(CISOPlatform Summit & SACON 2024) Gen AI & Deepfake In Overall Security.pdf
(CISOPlatform Summit & SACON 2024) Gen AI & Deepfake In Overall Security.pdf
 
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
 
Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024
 
Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
 
Tailored CRM Software Development for Enhanced Customer Insights
Tailored CRM Software Development for Enhanced Customer InsightsTailored CRM Software Development for Enhanced Customer Insights
Tailored CRM Software Development for Enhanced Customer Insights
 
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
 
(CISOPlatform Summit & SACON 2024) Regulation & Response In Banks.pdf
(CISOPlatform Summit & SACON 2024) Regulation & Response In Banks.pdf(CISOPlatform Summit & SACON 2024) Regulation & Response In Banks.pdf
(CISOPlatform Summit & SACON 2024) Regulation & Response In Banks.pdf
 
Vulnerability Management: A Comprehensive Overview
Vulnerability Management: A Comprehensive OverviewVulnerability Management: A Comprehensive Overview
Vulnerability Management: A Comprehensive Overview
 
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
High Profile Girls call Service Pune 000XX00000 Provide Best And Top Girl Ser...
 
The Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF GuideThe Role of IoT in Australian Mobile App Development - PDF Guide
The Role of IoT in Australian Mobile App Development - PDF Guide
 
Mule Experience Hub and Release Channel with Java 17
Mule Experience Hub and Release Channel with Java 17Mule Experience Hub and Release Channel with Java 17
Mule Experience Hub and Release Channel with Java 17
 
Evolution of iPaaS - simplify IT workloads to provide a unified view of data...
Evolution of iPaaS - simplify IT workloads to provide a unified view of  data...Evolution of iPaaS - simplify IT workloads to provide a unified view of  data...
Evolution of iPaaS - simplify IT workloads to provide a unified view of data...
 
Types of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technologyTypes of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technology
 

Parallel and Async Programming With C#

  • 1. Rainer Stropek | software architects gmbh Parallel & Async in C#
  • 2. Agenda Parallele und asynchrone Programmierung sind von einem Nischenthema zu einer wichtigen Herausforderung für jeden .NET-Entwickler geworden. Spätestens am Beispiel der Windows Runtime (WinRT), dem API für Windows Store Apps, sieht man, welche Bedeutung dem Thema beizumessen ist: In WinRT sind nahezu alle Funktionen, die etwas länger dauern könnten, asynchron. Dadurch werden die vorhandenen Ressourcen besser genutzt und das UI friert nie ein. Rainer Stropek beginnt in seinem Workshop mit Grundlagen über parallele und asynchrone Programmierung mit .NET. Er zeigt TPL und PLINQ in Aktion. Darauf aufbauend geht er auf die neuen C#-Schlüsselwörter async und await ein. Design-Guidelines für moderne, Task-basierende APIs sind der Abschluss des Workshops. Sie erfahren, wie Task Cancellation, Progress Reporting etc. richtig gemacht werden. Rainer stellt zum Workshop ein Slidedeck zum Nachschlagen zur Verfügung, im Workshop selbst stehen aber praktische Beispiele (C#) im Vordergrund.
  • 3. Introduction • software architects gmbh • Rainer Stropek – Developer, Speaker, Trainer – MVP for Windows Azure since 2010 – rainer@timecockpit.com – @rstropek http://www.timecockpit.com http://www.timecockpit.com/devblog
  • 4. Functional Programming Concepts In C# A Short Recap…
  • 5. A short recap… • Lambda expressions in C# • Anonymous delegates – Func, Func<T> – Action, Action<T> • Concepts of functional programming in C# – Use first-class functions to reduce duplication of code • Application of functional programming in LINQ • BTW – This has been around since C# 2 and/or 3.x
  • 6. public delegate int MathOperation(int x, int y); static void Main(string[] args) { MathOperation delegateOperation = Add; // Anonymous delegate MathOperation anonymousDelegateOperation = delegate(int num1, int num2) { return num1 + num2; }; // Func<T> Func<int, int, int> operationFunction = Add; // Simple lambda functions operationFunction = (x, y) => x + y; delegateOperation = (x, y) => x + y; } public static int Add(int num1, int num2) { return num1 + num2; }
  • 7. public delegate string[] GenerateDataOperation(int numberOfElements); static void Main(string[] args) { GenerateDataOperation generateOperation = NameGenerator; // Multi-line anonymous delegate GenerateDataOperation anonymousGenerateOperation = delegate(int numberOfElements) { var result = new string[numberOfElements]; for (int i = 0; i < numberOfElements; i++) { result[i] = string.Format("line_{0}", i); } return result; }; // Multi-line lambda functions Func<int, string[]> generatorFunction = (numberOfElements) => { var result = new string[numberOfElements]; for (int i = 0; i < numberOfElements; i++) { result[i] = string.Format("line_{0}", n); } return result; }; }
  • 8. Do we need some recap on LINQ? • IEnumerable<T> – Covariance • C# LINQ syntax • LINQ Support in .NET Framework • Lambda expressions as data – IQueryable<T> – Expression trees
  • 9. // Result of a method var res5 = from training in demoData select training.Attendees.First(); // Result of a property var res6 = from training in demoData Map part of the famous select training.Duration; map/reduce concept // Anonymous type var res7 = from training in demoData select new { Even if you do not like var, training.Title, here you have to use it NumberOfAttendees = training.Attendees.Count() }; // Instance of existing type var res8 = from training in demoData select new TrainingInfo { Title = training.Title, NumberOfAttendees = training.Attendees.Count() };
  • 10. Query vs. Method Syntax • Linq queries are a concept of the language, not the .NET Framework • Compiler converts query into method calls Pass first-class function as parameter to a LINQ method
  • 11. public static void SelectManyDemo() { var strings = new [] { "This is string number one", "This might be a second string" Method }; Syntax var result = strings .SelectMany(s => s.Split(' ')) Reduce .Distinct() .Select(s => s.ToLower()) .OrderBy(s => s); foreach (var line in result) Map { Console.WriteLine(line); } }
  • 12. var res12 = from training in demoData Method syntax group training embedded in LINQ by new { training.Title, query NumberOfAttendees = training.Attendees.Count( a => a.CountryOfOrigin == "AT") } into trainingGroup where trainingGroup.Key.NumberOfAttendees > 0 select new { trainingGroup.Key.Title, AttendeesFromAustria = trainingGroup.Key.NumberOfAttendees };
  • 13. Parallel Programming Task Parallel Library
  • 14. Goals • Understand Tasks  foundation for async/await • Take a close look at C# 4.5‘s stars async/await
  • 15. Recommended Reading • Joseph Albahari, Threading in C# (from his O‘Reilly book C# 4.0 in a Nutshell) • Patterns of Parallel Programming • Task-based Asynchronous Pattern • A technical introduction to the Async CTP • Using Async for File Access • Async Performance: Understanding the Costs of Async and Await (MSDN Magazine)
  • 16. See also Patterns of Parallel Programming
  • 17. Multithreading Pre .NET 4 .NET 4 • System.Threading • System.Threading. Namespace Tasks Namespace • Thread Klasse • Task und Task<TResult> Klassen • ThreadPool Klasse • TaskFactory Klasse • Parallel Klasse
  • 18. Kurzer Überblick über Tasks • Starten – Parallel.Invoke(…) Nicht in Silverlight  – Task.Factory.StartNew(…) • Warten – myTask.Wait() – Task.WaitAll – Task.WaitAny – Task.Factory.ContinueWhenAll(…) – Task.Factory.ContinueWhenAny(…) • Verknüpfen – Task.Factory.StartNew(…, TaskCreationOptions.AttachedToParent); • Abbrechen – Cancellation Tokens MSDN
  • 19. Schleifen - Parallel.For var source = new double[Program.Size]; var destination = new double[Program.Size]; Console.WriteLine(MeasuringTools.Measure(() => { for (int i = 0; i < Program.Size; i++) { source[i] = (double)i; } for (int i = 0; i < Program.Size; i++) { destination[i] = Math.Pow(source[i], 2); } })); Console.WriteLine(MeasuringTools.Measure(() => { Parallel.For(0, Program.Size, (i) => source[i] = (double)i); Parallel.For(0, Program.Size, (i) => destination[i] = Math.Pow(source[i], 2)); }));
  • 20. Schleifen - Parallel.For • Unterstützung für Exception Handling • Break und Stop Operationen – Stop: Keine weiteren Iterationen – Break: Keine Iterationen nach dem aktuellen Index mehr – Siehe dazu auch ParallelLoopResult • Int32 und Int64 Laufvariablen • Konfigurationsmöglichkeiten (z.B. Anzahl an Threads) • Schachtelbar – Geteilte Threading-Ressourcen • Effizientes Load Balancing Nicht selbst entwickeln! • U.v.m.
  • 21. Schleifen - Parallel.ForEach Console.WriteLine( "Serieller Durchlauf mit foreach: {0}", MeasuringTools.Measure(() => { double sumOfSquares = 0; foreach (var square in Enumerable.Range(0, Program.Size).Select( i => Math.Pow(i, 2))) { sumOfSquares += square; } })); Hoher Aufwand für Console.WriteLine( abgesicherten Zugriff auf "Paralleler Durchlauf mit foreach: {0}", MoveNext/Current MeasuringTools.Measure(() =>  Parallele Version oft { langsamer double sumOfSquares = 0; Parallel.ForEach(Enumerable.Range(0, Program.Size) .Select(i => Math.Pow(i, 2)), square => sumOfSquares += square); }));
  • 22. Von LINQ zu PLINQ LINQ PLINQ var result = source var result = source .Where(…) .AsParallel() .Select(…) .Where(…) .Select(…) Aus IEnumerable wird ParallelQuery Tipp: AsOrdered() erhält die Sortierreihenfolge
  • 23. Performancetipps für PLINQ • Allokieren von Speicher in parallelem Lambdaausdruck vermeiden – Sonst kann Speicher + GC zum Engpass werden – Wenn am Server: Server GC • False Sharing vermeiden • Bei zu kurzen Delegates ist Koordinationsaufwand für Parallelisierung oft höher als Performancegewinn –  Expensive Delegates – Generell: Auf richtige Granularität der Delegates achten • AsParallel() kann an jeder Stelle im LINQ Query stehen –  Teilweise serielle, teilweise parallele Ausführung möglich • Über Environment.ProcessorCount kann Anzahl an Kernen ermittelt werden • Messen, Messen, Messen!
  • 24. Was läuft hier falsch? (Code) var result = new List<double>(); Console.WriteLine( "Paralleler Durchlauf mit Parallel.ForEach: {0}", MeasuringTools.Measure(() => { Parallel.ForEach( Parallel.ForEach verwendet source.AsParallel(), IEnumerable<T>  unnötige i => Merge-Schritte { if (i % 2 == 0) { lock (result) { result.Add(i); } } }); }));
  • 25. Was läuft hier falsch? (Code)  Console.WriteLine( "Paralleler Durchlauf mit Parallel.ForAll: {0}", MeasuringTools.Measure(() => { source.AsParallel().ForAll( i => { if (i % 2 == 0) { lock (result) { result.Add(i); } } }); })); Lock-free Collection wäre überlegenswert!
  • 26. Was läuft hier falsch? (Code) Console.WriteLine( "Serielles Lesen: {0}", Optimal für Parallelisierung MeasuringTools.Measure(() => selbst bei einem Core (IO-Bound { Waits) foreach (var url in urls) { var request = WebRequest.Create(url); using (var response = request.GetResponse()) { using (var stream = response.GetResponseStream()) { var content = new byte[1024]; while (stream.Read(content, 0, 1024) != 0) ; } } } }));
  • 27. Was läuft hier falsch? (Code) Console.WriteLine( Anzahl Threads = Anzahl Cores; "Paralleles Lesen: {0}", könnte mehr sein, da IO-Bound MeasuringTools.Measure(() => { waits Parallel.ForEach(urls, url => { var request = WebRequest.Create(url); using (var response = request.GetResponse()) { using (var stream = response.GetResponseStream()) { var content = new byte[1024]; while (stream.Read(content, 0, 1024) != 0) ; } } }); })); Parallel.ForEach( urls, new ParallelOptions() { MaxDegreeOfParallelism = urls.Length }, url => { … });
  • 28. Was läuft hier falsch? (Code) Console.WriteLine(  "Paralleles Lesen: {0}", MeasuringTools.Measure(() => { urls.AsParallel().WithDegreeOfParallelism(urls.Length) .Select(url => WebRequest.Create(url)) .Select(request => request.GetResponse()) .Select(response => new { Response = response, Stream = response.GetResponseStream() }) .ForAll(stream => { var content = new byte[1024]; while (stream.Stream.Read(content, 0, 1024) != 0) ; stream.Stream.Dispose(); stream.Response.Close(); }); })); OK für Client, tödlich für Server! Wenn Anzahl gleichzeitiger User wichtig ist sind andere Lösungen vorzuziehen.
  • 29. private static void DoSomething() { Action<Action> measure = (body) => { var startTime = DateTime.Now; body(); Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, This process will run in DateTime.Now - startTime); parallel }; Action calcProcess = () => { for (int i = 0; i < 100000000; i++);}; measure(() => Task.WaitAll(Enumerable.Range(0, 10) .Select(i => Task.Run(() => measure(calcProcess))) .ToArray())); } Note that we use the new Task.Run function here; previously you had to use Task.Factory.StartNew
  • 30. Action<Action> measure = (body) => { var startTime = DateTime.Now; body(); Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now - startTime); }; Action calcProcess = () => { for (int i = 0; i < 350000000; i++);}; Action ioProcess = () => { Thread.Sleep(1000); }; Note that this task is not compute-bound // ThreadPool.SetMinThreads(5, 5); measure(() =>{ Task.WaitAll(Enumerable.Range(0, 10) .Select(i => Task.Run(() => measure(ioProcess))) .ToArray()); });
  • 31. Action<Action> measure = (body) =>{ var startTime = DateTime.Now; body(); Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now - startTime); }; Action calcProcess = () => { for (int i = 0; i < 350000000; i++);}; Action ioProcess = () => { Thread.Sleep(1000); }; ThreadPool.SetMinThreads(5, 5); measure(() => Enumerable.Range(0, 10) .AsParallel() .WithDegreeOfParallelism(5) .ForAll(i => measure(ioProcess)));
  • 32. Excursus - PLINQ • Use .AsParallel to execute LINQ query in parallel • Be careful if you care about ordering – Use .AsOrdered if necessary • Use .WithDegreeOfParallelism in case of IO-bound tasks • Use .WithCancellation to enable cancelling
  • 33. private static void DoSomethingElse() { Func<int, int> longRunningFunc = (prevResult) => { Thread.Sleep(1000); return prevResult + 42; }; Concat tasks using ContinueWith var task = Task.Run(() => longRunningFunc(0)) .ContinueWith(t => longRunningFunc(t.Result)) .ContinueWith(t => longRunningFunc(t.Result)); task.Wait(); Console.WriteLine(task.Result); } Wait for completion of a task.
  • 34. Exception Handling • AggregateException • Remove nested Aggregate Exceptions with Flatten • Use CancellationToken for cooperative cancellation • Use the Handle method instead of loop over Aggregate Exceptions • Use Task.Exception
  • 35. var task1 = Task.Factory.StartNew(() => { throw new MyCustomException("I'm bad, but not too bad!"); }); try { task1.Wait(); } catch (AggregateException ae) { // Assume we know what's going on with this particular exception. // Rethrow anything else. AggregateException.Handle provides // another way to express this. See later example. foreach (var e in ae.InnerExceptions) { if (e is MyCustomException) { Console.WriteLine(e.Message); } else { throw; } } }
  • 36. var task1 = Task.Factory.StartNew(() => { var child1 = Task.Factory.StartNew(() => { var child2 = Task.Factory.StartNew(() => { throw new MyCustomException("Attached child2 faulted."); }, TaskCreationOptions.AttachedToParent); // Uncomment this line to see the exception rethrown. // throw new MyCustomException("Attached child1 faulted."); }, TaskCreationOptions.AttachedToParent); }); try { task1.Wait(); } catch (AggregateException ae) { foreach (var e in ae.Flatten().InnerExceptions) { … } // or ... // ae.Flatten().Handle((ex) => ex is MyCustomException); }
  • 37. var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; var task1 = Task.Factory.StartNew(() => { CancellationToken ct = token; while (someCondition) { // Do some work... Thread.SpinWait(50000); ct.ThrowIfCancellationRequested(); } }, token); // No waiting required.
  • 38. foreach (var e in ae.InnerExceptions) { if (e is MyCustomException) { Console.WriteLine(e.Message); } else { throw; } } ae.Handle((ex) => { return ex is MyCustomException; });
  • 39. var task1 = Task.Factory.StartNew(() => { throw new MyCustomException("Task1 faulted."); }) .ContinueWith((t) => { Console.WriteLine("I have observed a {0}", t.Exception.InnerException.GetType().Name); }, TaskContinuationOptions.OnlyOnFaulted);
  • 40. Thread Synchronisation • Use C# lock statement to control access to shared variables – Under the hoods Monitor.Enter and Monitor.Exit is used – Quite fast, usually fast enough – Only care for lock-free algorithms if really necessary • Note that a thread can lock the same object in a nested fashion
  • 41. // Source: C# 4.0 in a Nutshell, O‘Reilly Media class ThreadSafe { static readonly object _locker = new object(); static int _val1, _val2; static void Go() { lock (_locker) { if (_val2 != 0) Console.WriteLine (_val1 / _val2); _val2 = 0; } } } // This is what happens behind the scenes bool lockTaken = false; try { Monitor.Enter(_locker, ref lockTaken); // Do your stuff... } finally { if (lockTaken) Monitor.Exit(_locker); }
  • 42. // Provide a factory for instances of the Random class per thread var tlr = new ThreadLocal<Random>( () => new Random(Guid.NewGuid().GetHashCode())); var watch = Stopwatch.StartNew(); var tasks = // Run 10 tasks in parallel Enumerable.Range(0, 10) .Select(_ => Task.Run(() => // Create a lot of randoms between 0 and 9 and calculate // the sum Enumerable.Range(0, 1000000) .Select(__ => tlr.Value.Next(10)) .Sum())) .ToArray(); Task.WaitAll(tasks); // Calculate the total Console.WriteLine(tasks.Aggregate<Task<int>, int>( 0, (agg, val) => agg + val.Result)); Console.WriteLine(watch.Elapsed); Do you think this is a good watch = Stopwatch.StartNew(); solution?
  • 43. // Provide a factory for instances of the Random class per thread var tlr = new ThreadLocal<Random>( () => new Random(Guid.NewGuid().GetHashCode())); var watch = Stopwatch.StartNew(); Console.WriteLine( ParallelEnumerable.Range(0, 10000000) .Select(_ => tlr.Value.Next(10)) .Sum()); Console.WriteLine(watch.Elapsed); Prefer PLINQ over TPL because it automatically breaks the workload into packages.
  • 44. Alternatives For lock • Mutex • Semaphore(Slim) • ReaderWriterLock(Slim) • Not covered here in details
  • 45. Thread Synchronization • AutoResetEvent – Unblocks a thread once when it receives a signal from another thread • ManualResetEvent(Slim) – Like a door, opens and closes again • CountdownEvent – New in .NET 4 – Unblocks if a certain number of signals have been received • Barrier class – New in .NET 4 – Not covered here • Wait and Pulse – Not covered here
  • 46. Producer/Consumer Was läuft hier falsch? (Code) var buffer = new Queue<long>(); var cancelTokenSource = new CancellationTokenSource(); var done = false; var producer = Task.Factory.StartNew((cancelTokenObj) => { var counter = 10000000; var cancelToken = (CancellationToken)cancelTokenObj; try { while (!cancelToken.IsCancellationRequested && counter-- > 0) { // Here we get some data (e.g. reading it from a file) var value = DateTime.Now.Ticks; // Write it to buffer with values that have to be processed buffer.Enqueue(value); } } finally { done = true; } buffer wird nicht gelockt }, cancelTokenSource.Token);
  • 47. Producer/Consumer Was läuft hier falsch? (Code) var consumer = Task.Factory.StartNew((cancelTokenObj) => { var cancelToken = (CancellationToken)cancelTokenObj; while (!cancelToken.IsCancellationRequested && !done) { // Get the next value to process lock (buffer) { Prüfung ob leer fehlt var value = buffer.Dequeue(); } // Here we do some expensive procesing Thread.SpinWait(1000); } }, cancelTokenSource.Token); Consumer ist viel langsamer als Producer  Producer überschwemmt Consumer mit Daten
  • 48. Collections für parallele Programmierung • System.Collections.Concurrent für Thread- Safe Collections – BlockingCollection<T> Blocking und Bounding-Funktionen – ConcurrentDictionary<T> – ConcurrentQueue<T> – ConcurrentStack<T> – ConcurrentBag<T> • Optimal zur Umsetzung von Pipelines – Datei wird gelesen, gepackt, verschlüsselt, geschrieben
  • 49. Producer/Consumer Was läuft hier falsch? (Code) var buffer = new BlockingCollection<long>(10); var cancelTokenSource = new CancellationTokenSource(); var producer = Task.Factory.StartNew((cancelTokenObj) => { var counter = 10000000; var cancelToken = (CancellationToken)cancelTokenObj; try { while (!cancelToken.IsCancellationRequested && counter-- > 0) { // Here we get some data (e.g. reading it from a file) var value = DateTime.Now.Ticks; // Write it to the buffer with values that have to be processed buffer.Add(value); }  } finally { buffer.CompleteAdding(); } }, cancelTokenSource.Token);
  • 50. Producer/Consumer Was läuft hier falsch? (Code) var consumer = Task.Factory.StartNew((cancelTokenObj) => { var cancelToken = (CancellationToken)cancelTokenObj; foreach (var value in buffer.GetConsumingEnumerable()) { if ( cancelToken.IsCancellationRequested ) { break; }  // Here we do some expensive procesing Thread.SpinWait(1000); } }, cancelTokenSource.Token);
  • 51. Async Programming The big new thing in C# 5
  • 52. private static void DownloadSomeTextSync() { using (var client = new WebClient()) { Console.WriteLine( client.DownloadString(new Uri(string.Format( "http://{0}", (Dns.GetHostAddresses("www.basta.net"))[0])))); } } Synchronous version of the code; would block UI thread
  • 53. private static void DownloadSomeText() { var finishedEvent = new AutoResetEvent(false); // Notice the IAsyncResult-pattern here Dns.BeginGetHostAddresses("www.basta.net", GetHostEntryFinished, finishedEvent); finishedEvent.WaitOne(); } private static void GetHostEntryFinished(IAsyncResult result) { var hostEntry = Dns.EndGetHostAddresses(result); using (var client = new WebClient()) { // Notice the Event-based asynchronous pattern here client.DownloadStringCompleted += (s, e) => { Console.WriteLine(e.Result); ((AutoResetEvent)result.AsyncState).Set(); }; client.DownloadStringAsync(new Uri(string.Format( "http://{0}", hostEntry[0].ToString()))); } Notice that control flow is not clear } any more.
  • 54. private static void DownloadSomeText() { var finishedEvent = new AutoResetEvent(false); // Notice the IAsyncResult-pattern here Dns.BeginGetHostAddresses( "www.basta.net", (result) => { var hostEntry = Dns.EndGetHostAddresses(result); using (var client = new WebClient()) { // Notice the Event-based asynchronous pattern here client.DownloadStringCompleted += (s, e) => { Console.WriteLine(e.Result); ((AutoResetEvent)result.AsyncState).Set(); }; client.DownloadStringAsync(new Uri(string.Format( "http://{0}", hostEntry[0].ToString()))); } }, finishedEvent); finishedEvent.WaitOne(); Notice how lambda expression } can make control flow clearer
  • 55. Notice the use of the new Task Async Pattern APIs in .NET 4.5 here private static void DownloadSomeTextUsingTask() { Dns.GetHostAddressesAsync("www.basta.net") .ContinueWith(t => { using (var client = new WebClient()) { return client.DownloadStringTaskAsync(new Uri(string.Format( "http://{0}", t.Result[0].ToString()))); } }) .ContinueWith(t2 => Console.WriteLine(t2.Unwrap().Result)) .Wait(); } Notice the use of lambda Notice how code has become expressions all over the methods shorter and more readable
  • 56. Rules For Async Method Signatures • Method name ends with Async • Return value – Task if sync version has return type void – Task<T> if sync version has return type T • Avoid out and ref parameters – Use e.g. Task<Tuple<T1, T2, …>> instead
  • 57. // Synchronous version private static void DownloadSomeTextSync() { using (var client = new WebClient()) { Console.WriteLine( client.DownloadString(new Uri(string.Format( "http://{0}", (Dns.GetHostAddresses("www.basta.net"))[0])))); } } Notice how similar the sync and async versions are! // Asynchronous version private static async void DownloadSomeTextUsingTaskAsync() { using (var client = new WebClient()) { Console.WriteLine( await client.DownloadStringTaskAsync(new Uri(string.Format( "http://{0}", (await Dns.GetHostAddressesAsync("www.basta.net"))[0])))); } }
  • 58. private static async void DownloadSomeTextUsingTaskAsync2() { using (var client = new WebClient()) { try { var ipAddress = await Dns.GetHostAddressesAsync("www.basta.net"); var content = await client.DownloadStringTaskAsync( new Uri(string.Format("htt://{0}", ipAddress[0]))); Console.WriteLine(content); } catch (Exception) { Console.WriteLine("Exception!"); } } } Let’s check the generated code and debug the async code
  • 59. Guidelines for async/await • If Task ended in Canceled state, OperationCanceledExceptio n will be thrown
  • 60. private async static void CancelTask() { try { var cancelSource = new CancellationTokenSource(); var result = await DoSomethingCancelledAsync(cancelSource.Token); Console.WriteLine(result); } catch (OperationCanceledException) { Console.WriteLine("Cancelled!"); } } private static Task<int> DoSomethingCancelledAsync(CancellationToken token) { // For demo purposes we ignore token and always return a cancelled task var result = new TaskCompletionSource<int>(); result.SetCanceled(); return result.Task; } Note usage of TaskCompletionSource<T> here
  • 61. Note that async API of WebClient uses existing cancellation logic instead of CancellationTokenSource
  • 63. Guidelines for async/await • Caller runs in parallel to awaited methods • Async methods sometimes do not run async (e.g. if task is already completed when async is reached)
  • 64. Guidelines for async/await (UI Layer) • async/await use SynchronizationContext to execute the awaiting method  UI thread in case of UI layer • Use Task.ConfigureAwait to disable this behavior – E.g. inside library to enhance performance
  • 65. public partial class MainWindow : Window { public MainWindow() { this.DataContext = this; this.ListBoxContent = new ObservableCollection<string>(); this.InitializeComponent(); this.ListBoxContent.Add("Started"); this.Loaded += async (s, e) => { for (int i = 0; i < 10; i++) { ListBoxContent.Add(await Task.Run(() => { Thread.Sleep(1000); return "Hello World!"; })); } this.ListBoxContent.Add("Finished"); }; } public ObservableCollection<string> ListBoxContent { get; private set; }
  • 67. Guidelines For Implementing Methods Ready For async/await • Return Task/Task<T> • Use postfix Async • If method support cancelling, add parameter of type System.Threading.CancellationToken • If method support progress reporting, add IProgress<T> parameter • Only perform very limited work before returning to the caller (e.g. check arguments) • Directly throw exception only in case of usage errors
  • 68. public class Program : IProgress<int> { static void Main(string[] args) { var finished = new AutoResetEvent(false); PerformCalculation(finished); finished.WaitOne(); } private static async void PerformCalculation(AutoResetEvent finished) { Console.WriteLine(await CalculateValueAsync( 42, CancellationToken.None, new Program())); finished.Set(); } public void Report(int value) { Console.WriteLine("Progress: {0}", value); }
  • 69. private static Task<int> CalculateValueAsync( int startingValue, CancellationToken cancellationToken, IProgress<int> progress) { if (startingValue < 0) { // Usage error throw new ArgumentOutOfRangeException("startingValue"); } return Task.Run(() => { int result = startingValue; for (int outer = 0; outer < 10; outer++) { cancellationToken.ThrowIfCancellationRequested(); // Do some calculation Thread.Sleep(500); result += 42; progress.Report(outer + 1); } return result; }); Note that this pattern is good for } compute-bound jobs }
  • 70. private static async void PerformCalculation(AutoResetEvent finished) { try { var cts = new CancellationTokenSource(); Task.Run(() => { Thread.Sleep(3000); cts.Cancel(); }); var result = await CalculateValueAsync( 42, cts.Token, new Program()); } catch (OperationCanceledException) { Console.WriteLine("Cancelled!"); } finished.Set(); } Note cancellation and handling of OperationCanceledException.
  • 71. private static Task<int> CalculateValueAsync( int startingValue, CancellationToken cancellationToken, IProgress<int> progress) { if (startingValue < 0) { // By definition the result has to be 0 if startingValue < 0 return Task.FromResult(0); } return Task.Run(() => { […] }); } Note that you could use Note how Task.FromResult is used TaskCompletionSource instead to return a pseudo-task
  • 72. Was läuft hier falsch? (Code) Console.WriteLine( "Paralleles Lesen mit TaskFactory: {0}", MeasuringTools.Measure(() => { var tasks = new Task[urls.Length]; for (int i = 0; i < urls.Length; i++) { tasks[i] = Task.Factory.StartNew(() => ReadUrl(urls[i])); } Task.WaitAll(tasks); } )); … Delegate verwendet Wert von i aus dem Main Thread  private static void ReadUrl(object url) IndexOutOfRangeException { … }
  • 73. Was läuft hier falsch? (Code) // Variante 1 … Durch lokale Variable wird delegate var tasks = new Task[urls.Length]; unabhängig; mehr zum Thema unter dem for (int i = 0; i < urls.Length; i++) Schlagwort Closures { var tmp = i; tasks[i] = Task.Factory.StartNew(() => ReadUrl(urls[tmp])); } … // Variante 2 var tasks = new Task[urls.Length]; State object wird an delegate übergeben for (int i = 0; i < urls.Length; i++) { tasks[i] = Task.Factory.StartNew(ReadUrl, urls[i]); }
  • 74. for (var i = 0; i < 10; i++) { new Thread(() => Console.Write(i)).Start(); You have to be careful } with closures and multi-threading. for (var i = 0; i < 10; i++) { var temp = i; new Thread(() => Console.Write(temp)).Start(); }
  • 75. // Setup timer using an action (notice the closure here) var startTime = DateTime.Now; using (var timer = new System.Threading.Timer( _ => progressIndicator(DateTime.Now - startTime), null, 1000, 1000)) { Thread.Sleep(3100); }
  • 76. F&A Danke für die Teilnahme!
  • 77. is the leading time tracking solution for knowledge workers. Graphical time tracking calendar, automatic tracking of your work using signal trackers, high level of extensibility and customizability, full support to work offline, and SaaS deployment model make it the optimal choice especially in the IT consulting business. Try for free and without any risk. You can get your trial account at http://www.timecockpit.com. After the trial period you can use for only 0,20€ per user and month without a minimal subscription time and without a minimal number of users.
  • 78. ist die führende Projektzeiterfassung für Knowledge Worker. Grafischer Zeitbuchungskalender, automatische Tätigkeitsaufzeichnung über Signal Tracker, umfassende Erweiterbarkeit und Anpassbarkeit, volle Offlinefähigkeit und einfachste Verwendung durch SaaS machen es zur Optimalen Lösung auch speziell im IT-Umfeld. Probieren Sie kostenlos und ohne Risko einfach aus. Einen Testzugang erhalten Sie unter http://www.timecockpit.com. Danach nutzen Sie um nur 0,20€ pro Benutzer und Tag ohne Mindestdauer und ohne Mindestbenutzeranzahl.