Asynchroniczny C#

Cezary Walenciuk

Asynchroniczny C#

@walenciukC

Speaker
Asynchroniczny C# ma wiele pu艂apek

What

                    

                        private static string result;

                        static void Main()
                        {
                            SaySomething();
                            Console.WriteLine(result);
                        }
                
                        static async Task<int> SaySomething()
                        {
                            await Task.Delay(10);
                            result = "Hello!";
                            return 1;
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

What

                    

                        private static string result;

                        static void Main()
                        {
                            SaySomething();
                            Console.WriteLine(result);
                        }
                
                        static async Task<int> SaySomething()
                        {
                            await Task.Delay(10);
                            result = "Hello!";
                            return 1;
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

[NIC]

What 2

                    

                        private static string result;

                        static void Main()
                        {
                            SaySomething();
                            Console.WriteLine(result);
                        }
                
                        static async Task<int> SaySomething()
                        {
                            Thread.Sleep(10);
                            result = "Hello!";
                            return 1;
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

Hello

Asynchroniczny C#?

Asynchroniczny C#?

Async i Await?

Async i Await?

Czym jest w膮tek?

Czym jest w膮tek?

                
                    static void Main(string[] args)
                    {
                        int a = 11;
                        int b = 22;
                        int c = 33;
                        int d = 44;
                        int f = 55;
                    
                        a = a + b;
                        b = c + d;
                        c = a + b;
                        d = f + d;
                        f = a + b + c + d / 4;
                    }
                
            
                
            IL_0000: nop
            IL_0001: ldc.i4.s 11
            IL_0003: stloc.0
            IL_0004: ldc.i4.s 22
            IL_0006: stloc.1
            IL_0007: ldc.i4.s 33
            IL_0009: stloc.2
            IL_000a: ldc.i4.s 44
            IL_000c: stloc.3
            IL_000d: ldc.i4.s 55
            IL_000f: stloc.s 4
            IL_0011: ldloc.0
            IL_0012: ldloc.1
            IL_0013: add
            IL_0014: stloc.0
            IL_0015: ldloc.2
            IL_0016: ldloc.3
            IL_0017: add
            IL_0018: stloc.1
            IL_0019: ldloc.0
            IL_001a: ldloc.1
            IL_001b: add
            IL_001c: stloc.2
            IL_001d: ldloc.s 4
            IL_001f: ldloc.3
            IL_0020: add
            IL_0021: stloc.3
            IL_0022: ldloc.0
            IL_0023: ldloc.1
            IL_0024: add
            IL_0025: ldloc.2
            IL_0026: add
            IL_0027: ldloc.3
            IL_0028: ldc.i4.4
            IL_0029: div
            IL_002a: add
            IL_002b: stloc.s 4
            IL_002d: ret
        
    
W膮tek, a sprz臋t

W膮tek, a sprz臋t

W膮tek, a sprz臋t

  1. Ile rdzeni ma tw贸j jeden procesor?
W idealnym 艣wiecie mia艂by艣 tyle rdzeni w procesorze ile masz w膮tk贸w
blog
Copyright 漏 Cezary Walenciuk
blog
Copyright 漏 Cezary Walenciuk
blog
Copyright 漏 Cezary Walenciuk
blog
Copyright 漏 Cezary Walenciuk
blog
Copyright 漏 Cezary Walenciuk
blog
Copyright 漏 Cezary Walenciuk
blog
Copyright 漏 Cezary Walenciuk
blog
Copyright 漏 Cezary Walenciuk
W膮tek i jego priority w Windows

W膮tek i jego priority w Windows

Ustawienie wa偶no艣ci danego w膮tku je艣li masz uprawnienia Admina

                    
                        Process p = Process.GetCurrentProcess();
                        p.PriorityClass = ProcessPriorityClass.High;
            
                        Thread t = Thread.CurrentThread;
                        t.Priority = ThreadPriority.Normal;
                    
                

Jak widzisz mo偶na zmieni膰 priorytet swojego w艂asnego procesu
Kwant Czasu, co jest?
blog
Copyright 漏 Cezary Walenciuk

W膮tki podsumowanie

Wielow膮tkowo艣膰 sama w sobie nie powinna by膰 celem
Poka偶 mi new Thread()
Warto pami臋ta膰, 偶e jest to rozwi膮zani przestarza艂e
Obecnie by膰 mo偶e u偶yteczne do absurdalnych d艂ugich zada艅 asychronicznych

Ustawienie wa偶no艣ci danego w膮tku

                    
                        static void Main(string[] args)
                        {
                            Thread thread = new Thread(new ThreadStart(Do));
                            thread.IsBackground = true;
                            thread.Start();
                            thread.Join();
                        }
                
                        public static void Do()
                        {}
                    
                

Ustawienie wa偶no艣ci danego w膮tku

                    
                        static void Main(string[] args)
                        {
                            Thread thread2 = new Thread(new ParameterizedThreadStart(Do2));
                            thread2.IsBackground = true;
                            thread2.Start("parametr");
                            thread2.Join();
                        }
                
                        public static void Do2(object par)
                        {}
                    
                

Je偶eli potrzebne Ci s膮 parametry, to pojawia si臋 nowa delegata

Tworzenie w膮tku new Thread

                    
                        static void Main(string[] args)
                        {
                            Thread thread = new Thread(new ThreadStart(DoEx));
                            thread.IsBackground = true;
                            thread.Start();
                            thread.Join();
                        }
            
                        public static void DoEx()
                        {
                            throw new Exception();
                        }
                    
                

Aplikacja wywala si臋 bez ostrze偶enia. Nie mo偶na tego zatrzyma膰.
Klasa ThreadPool

Czym jest ThreadPool

Czym jest ThreadPool

blog
Copyright 漏 Cezary Walenciuk

ThreadPool

                    
                        int workerThreadsMin; int IOCPThreadMin;

                        ThreadPool.GetMinThreads(out workerThreadsMin,
                            out IOCPThreadMin);
            
                        int workerThreadsMax; int IOCPThreadMax;
            
                        ThreadPool.GetMaxThreads(out workerThreadsMax,
                            out IOCPThreadMax);
            
                        ThreadPool.SetMaxThreads(1000, 32767);
                        ThreadPool.SetMinThreads(8, 8);
                    
                

Mo偶esz ustawi膰 liczb臋 w膮tk贸w. Liczba maksymalnych w膮tk贸w jest zale偶na od .NET Framework

Minimum?

ThreadPool

                    
                        Action a = (state) => { };

                        ThreadPool.
                        QueueUserWorkItem(a, "StanOk", true);
                    
                

Mo偶esz doda膰 "zadanie"(workitem) do puli.

ThreadPool

                    
                        static void Main(string[] args)
                        {
                            ThreadPool.QueueUserWorkItem(Do);
                        }
                
                        public static void Do(object? state)
                        {}
                    
                

Mo偶esz doda膰 "zadanie"(workitem) do puli.

ThreadPool

                    
                        static void Main(string[] args)
                        {
                            AppDomain.CurrentDomain.UnhandledException
                                += OnUnhandleException;
                            ThreadPool.QueueUserWorkItem(Do);
                        }
                
                        private static void OnUnhandleException(object sender, UnhandledExceptionEventArgs e)
                        {
                            Console.WriteLine("Terminacja? : " + e.IsTerminating);
                            Console.WriteLine("Przyczyna : " + e.ExceptionObject);
                        }
                
                        public static void Do(object? state)
                        {
                            throw new Exception();
                        }
                    
                

ThreadPool nie obs艂uguje wyj膮tk贸w
IAsyncResult, czyli jak kiedy艣 robi艂o si臋 asynchroniczne operacje

IAsyncResult, czyli jak kiedy艣 robi艂o si臋 asynchroniczne operacje

                    

                        static void Main(string[] args)
                        {              
                            Func method =
                                (int a) => { return a; };
                
                            IAsyncResult handle =
                                method.BeginInvoke(100,
                                new AsyncCallback(WhenDone),
                                new object());
                        }
                
                        private static void WhenDone(IAsyncResult ar)
                        {
                            var target = (Func)ar.AsyncState;
                            int result = target.EndInvoke(ar);
                
                            Console.WriteLine(result);
                        }
                    
                

Dla .NET Core 3.1 dostaj臋 PlatformNotSupported Exception
Kiedy艣 .NET mia艂 mn贸stwo metod BeginInvoke
By艂 to asynchronous programming model (APM)
Event Asynchronous Pattern

Event Asynchronous Pattern

                    
                        static void Main(string[] args)
                        {
                            var worker = new BackgroundWorker();
                
                            worker.DoWork += WorkerDoSomething;
                
                            worker.ProgressChanged += Worker_ProgressChanged;
                            worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
                            worker.RunWorkerAsync(worker);
                        }
                
                        private static void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
                        {}
                        private static void WorkerDoSomething(object sender, DoWorkEventArgs e)
                        {}
                        private static void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
                        {}
                    
                

Task API

Task i Task<T>

Thread.CurrentThread.IsBackground

                    
                        static void Main()
                        {
                            Task
                                .Factory
                                .StartNew(
                                    () => Console.WriteLine
                                    (Thread.CurrentThread.IsBackground))
                                .Wait();
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

Thread.CurrentThread.IsBackground 2

                    
                        static void Main()
                        {
                            Task
                                .Factory
                                .StartNew(
                                    () => Console.WriteLine
                                    (Thread.CurrentThread.IsBackground))
                                .Wait();
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

true

Task i Task<T>

Task i Task<T> Stany

Task i Task<T> Stany

Task i Task<T> Stany i w艂a艣ciwo艣ci warte do zapamietania

Task API

Task Delay

                    
                        static void Main(string[] args)
                        {
                            var d = DateTime.Now;
                            Console.WriteLine(d.Minute + ":" + d.Second);
                            Task.Delay(7000);
                            var d2 = DateTime.Now;
                            Console.WriteLine(d2.Minute + ":" + d2.Second);
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

Task Delay

                    
                        static void Main(string[] args)
                        {
                            var d = DateTime.Now;
                            Console.WriteLine(d.Minute + ":" + d.Second);
                            Task.Delay(7000);
                            var d2 = DateTime.Now;
                            Console.WriteLine(d2.Minute + ":" + d2.Second);
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

[To samo]

Task Delay

                    
                        static void Main(string[] args)
                        {
                            var d = DateTime.Now;
                            Console.WriteLine(d.Minute + ":" + d.Second);
                            Task t = Task.Delay(7000);
                            t.Wait();
                            var d2 = DateTime.Now;
                            Console.WriteLine(d2.Minute + ":" + d2.Second);
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

Task Delay

                    
                        static void Main(string[] args)
                        {
                            var d = DateTime.Now;
                            Console.WriteLine(d.Minute + ":" + d.Second);
                            Task t = Task.Delay(7000);
                            t.Wait();
                            var d2 = DateTime.Now;
                            Console.WriteLine(d2.Minute + ":" + d2.Second);
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

[R贸藕nica o 7 sekund]

Task Delay z async/await

                    
                        static async Task Main(string[] args)
                        {
                            var d = DateTime.Now;
                            Console.WriteLine(d.Minute + ":" + d.Second);
                            await Task.Delay(7000);
                            var d2 = DateTime.Now;
                            Console.WriteLine(d2.Minute + ":" + d2.Second);
                        }
                    
                

Task Delay z async/await

                    
                        static void Main()
                        {
                            var t = What();
                            Console.WriteLine(t.Status);
                        }

                        static Task What()
                        {
                            return new Task(
                                () => Console.WriteLine("1"));
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

Task Delay z async/await

                    
                        static void Main()
                        {
                            var t = What();
                            Console.WriteLine(t.Status);
                        }

                        static Task What()
                        {
                            return new Task(
                                () => Console.WriteLine("1"));
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

Created

task.Start() -> Legacy

                    
                        static void Main(string[] args)
                        {
                            Task task = new Task(Do);
                            task.Start();
                        }

                        private static void Do(){}
                    
                

task.Factory.StartNew() -> Legacy .NET 4.0+

                    
                        static void Main(string[] args)
                        {
                            Task task = Task.Factory.StartNew(Do);
                        }
                
                        private static void Do(){}
                    
                

task.Run() -> OK .NET 4.5+

                    
                        static void Main(string[] args)
                        {
                            Task task = Task.Run(Do);
                        }
                
                        private static void Do(){}
                    
                

task.Run() -> OK .NET 4.5+

                    
                        static void Main(string[] args)
                        {
                            Task task = Task.Run(Do);
                            task.Wait();
                
                            Task<int> task2 = Task.Run(Do2);
                            var r = task2.Result;
                        }

                        private static void Do() { }
                        private static int Do2() { return 1; }
                    
                

Kto艣 wam powie, aby nie korzysta膰 z "Wait" czy "Result", tylko z
...GetAwaiter().GetResult()
to w艂a艣nie robi s艂owo kluczowe await
R贸藕nica polega na tym, 偶e z "Wait" czy "Result" otrzymasz AggregateException

Task.Run vs Task.Factory.StartNew

Task.Factory.StartNew ma np.

task.Run() -> OK .NET 4.5+

                    
                        var parent = Task.Factory.StartNew(() =>
                        {
                            Console.WriteLine("Parent Start");
            
                            var child = Task.Factory.StartNew(() =>
                            {
                                Console.WriteLine("ChildTask Start");
                                Thread.Sleep(4000);
                                Console.WriteLine("ChildTask End");

                            }, TaskCreationOptions.AttachedToParent);
            
                            Console.WriteLine("Parent END");
                        });
            
                        parent.Wait();
                        Console.WriteLine("DEMO END");
                    
                

馃挕 Co pojawi si臋 w konsoli?

task.Run() -> OK .NET 4.5+

                    
                        var parent = Task.Factory.StartNew(() =>
                        {
                            Console.WriteLine("Parent Start");
            
                            var child = Task.Factory.StartNew(() =>
                            {
                                Console.WriteLine("ChildTask Start");
                                Thread.Sleep(4000);
                                Console.WriteLine("ChildTask End");

                            }, TaskCreationOptions.AttachedToParent);
            
                            Console.WriteLine("Parent END");
                        });
            
                        parent.Wait();
                        Console.WriteLine("DEMO END");
                    
                

馃挕 Co pojawi si臋 w konsoli?

Parent Start, Parent End, ChildTask Start, ChildTask End, DEMO END

DenyChildAttach

                    
                        var parent = Task.Factory.StartNew(() =>
                        {
                            Console.WriteLine("Parent Start");
            
                            var child = Task.Factory.StartNew(() =>
                            {
                                Console.WriteLine("ChildTask Start");
                                Thread.Sleep(4000);
                                Console.WriteLine("ChildTask End");

                            }, TaskCreationOptions.DenyChildAttach);
            
                            Console.WriteLine("Parent END");
                        });
            
                        parent.Wait();
                        Console.WriteLine("DEMO END");
                    
                

馃挕 Co pojawi si臋 w konsoli?

Parent Start,Parent END,DEMO END,ChildTask Start

task.Run() Wyj膮tek

                    
                        
                        Task<int> task = Task.Run(() =>
                        {
                            throw new AccessViolationException();
                            return -1;
                        });
                        Console.ReadKey();
                        
                        try
                        {
                            _ = task.Result;
                        }
                        catch (AggregateException ex)
                        {
                            if (ex.InnerExceptions is
                                AccessViolationException)
                            {
                                Console.WriteLine(ex.Message)
                            }
                        
                        }
                    
                

Co si臋 stanie, gdy nie b臋dziesz obserwowa艂 wyj膮tku w Tasku

task.Run() Wyj膮tek

                    
                        static void Main(string[] args)
                        {
                            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
                
                            var task = Task.Run(() => { throw new Exception(); });
                
                        }
                
                        private static void TaskScheduler_UnobservedTaskException(object sender, 
                            UnobservedTaskExceptionEventArgs e)
                        {
                            Console.WriteLine("Przegapi艂e艣 :" + e.Exception);
                            e.SetObserved();
                        }
                    
                

ContinueWith czyli po co stworzyl async i await

ContinueWith -> Legacy

                    
                        Task<int> t = Task.Run(() =>
                        {
                                return 44;
                        });
                                        
                        Task<int> t2 = t.ContinueWith(a =>
                        {
                                return t.Result + 66;
                        });
                                        
                        Console.WriteLine(t2.Result);
                        Console.Read();
                    
                

ContinueWith -> Legacy

                    
                        Task<int>t = Task.Run(() =>
                        {
                            return 44;
                        });
                        
                        Task<int> t2 = t.ContinueWith(a =>
                        {
                            return t.Result + 66;
                        },
                        TaskContinuationOptions.OnlyOnRanToCompletion);
                        
                        Task t3 = t.ContinueWith(a =>
                        {
                            Console.WriteLine("Error");

                        }, TaskContinuationOptions.OnlyOnFaulted);
                    
                

Task.ContinueWith - Legacy

CancellationTokenSource

ContinueWith -> Legacy

                    
                        var tokenSource2 = new CancellationTokenSource();
                        CancellationToken ct = tokenSource2.Token;
            
                        var t = Task.Run(() =>
                        {
                            ct.ThrowIfCancellationRequested();
                        });
            
                        try
                        {
                            t.Wait();
                        }
                        catch (OperationCanceledException e)
                        {
                            Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
                        }
                        finally
                        {
                            tokenSource2.Dispose();
                        }
                    
                

ContinueWith -> Legacy

                    
                        var tokenSource2 = new CancellationTokenSource();
                        CancellationToken ct = tokenSource2.Token;

                        tokenSource2.Cancel();

                        var t = Task.Run(() =>
                        {
                            
                        }, ct);

                        try
                        {
                            t.Wait();
                        }
                        catch (AggregateException e)
                        {
                            Console.WriteLine(e.InnerException);
                        }
                        finally
                        {
                            tokenSource2.Dispose();
                        }
                    
                

WaitAll i WaitAny

ContinueWith -> Legacy

                    
                        Task t1 = Task.Delay(2000);
                        Task t2 = Task.Delay(4000);
                        Task t3 = Task.Delay(6000);
            
                        Task.WaitAll(t1, t2, t3);
                        Task.WaitAny(t1, t2, t3);
                    
                

Unwrap

Task.Unwrap

                    
                        Task<Task<Task<int>>> t =
                            Task.Factory.StartNew
                            (() =>
                            {
                                return Task.Factory.StartNew(
                                () =>
                                Task.Run(() => { return 1; }));
            
                            });
            
                        var result = t.Result.Result.Result;
                    
                

Task.Unwrap

                    
                        Task<Task<Task<int>>> t =
                            Task.Factory.StartNew
                            (() =>
                            {
                                return Task.Factory.StartNew(
                                () =>
                                Task.Run(() => { return 1; }));
            
                            });
                                    
                        var unwrap = t.Unwrap();
                        var unwrap2 = unwrap.Unwrap();
                        var result = unwrap2.Result;
                    
                

Async i Await

Async i Await

                    

                        public int GiveNumber()
                        {
                            return -1;
                        }

                        public async Task<int> GiveNumberAsync()
                        {
                            return -1;
                        }
                    
                

Async i Await

                    

                        public async Task<int> GiveMeRandomNumberAsync()
                        {
                            var i = await GiveAnotherNumberAsync();
                            return await GiveNumberAsync();
                        }
                            
                        public async Task<int> GiveNumberAsync()
                        {
                            return 1;
                        }
                            
                        public async Task<int> GiveAnotherNumberAsync()
                        {
                            return 2;
                        }
                    
                

blog
Copyright 漏 Cezary Walenciuk
"async void" wywala proces gdy pojawi si臋 wyj膮tek
"async void" istnieje dla starych apilkacji
A dok艂adnie chodzi o event z parametrem wyj艣cia void

Async i Await

                    
                        static async Task Main()
                        {
                            var numbers = 
                                await File.ReadAllTextAsync(@"D:\numbers.txt");
                
                            Task<string> t = File.ReadAllTextAsync(@"D:\numbers2.txt");
                            await t;
                
                        }
                    
                

Async i Await

                    
                        static async Task Main()
                        {
                            WriteThread("Begin Main");
                            var a = await M1Async();
                            WriteThread("Middle Main");
                            var b = await M1Async();
                            Console.WriteLine(a + b);
                            WriteThread("End Main");
                            Console.ReadKey();
                        }
                
                        public static async Task<int> M1Async()
                        {
                            WriteThread("Begin M1Async");
                            var i = await M2Async();
                            WriteThread("End M1Async");
                            return i + 1;
                        }
                
                        public static async Task<int> M2Async()
                        {
                            WriteThread("At M2Async");
                            return -1;
                        }
                
                        public static void WriteThread(string helpfultoken)
                        {
                            Console.WriteLine(helpfultoken
                                + " : " + Thread.CurrentThread.ManagedThreadId);
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

Async i Await

                    
                        static async Task Main()
                        {
                            WriteThread("Begin Main");
                            var a = await M1Async();
                            WriteThread("Middle Main");
                            var b = await M1Async();
                            Console.WriteLine(a + b);
                            WriteThread("End Main");
                            Console.ReadKey();
                        }
                
                        public static async Task<int> M1Async()
                        {
                            WriteThread("Begin M1Async");
                            var i = await M2Async();
                            WriteThread("End M1Async");
                            return i + 1;
                        }
                
                        public static async Task<int> M2Async()
                        {
                            WriteThread("At M2Async");
                            return -1;
                        }
                
                        public static void WriteThread(string helpfultoken)
                        {
                            Console.WriteLine(helpfultoken
                                + " : " + Thread.CurrentThread.ManagedThreadId);
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

[Wsz臋dzie b臋dzie 1]
Jak kto?
Nie ma nowych w膮tk贸w?
Trywialne operacje nie tworz膮 nowych w膮tk贸w.
Chocia偶 async i await stworzy艂 maszyn臋 stan贸w

Async i Await : Stan zadania decyduje czy nowy w膮tek zostanie stworzony

                    
                        static async Task Main()
                        {
                            WriteThread("Begin Main");
                            var a = await M1Async();
                            WriteThread("Middle Main");
                            var b = await M1Async();
                            Console.WriteLine(a + b);
                            WriteThread("End Main");
                            Console.ReadKey();
                        }
                
                        public static async Task<int> M1Async()
                        {
                            WriteThread("Begin M1Async");
                            await Task.Delay(2000);
                            WriteThread("End M1Async");
                            return 0;
                        }
                
                        public static void WriteThread(string helpfultoken)
                        {
                            Console.WriteLine(helpfultoken
                                + " : " + Thread.CurrentThread.ManagedThreadId);
                        }
                    
                

馃挕 Co pojawi si臋 w konsoli?

1,1,4,4,4,4

Async i Await : maszyna stan贸w pami臋ta zako艅czenie

                    

                        static async Task Main()
                        {
                            Task<string> t = 
                            File.ReadAllTextAsync(@"D:\numbers2.txt");

                            await t;
                            await t;
                            await t;
                            await t;
                        }
                    
                

Rzeczy, o kt贸rych warto opowiedzie膰.
async eliding

async eliding

                    
                        static Task<int> M1()
                        {
                            return Task.FromResult(1);
                        }
                            
                        static async Task<int> M2()
                        {
                            return await M1();
                        }
                    
                

Przekazywanie Task贸w wy偶ej wydaje si臋 dobrym pomys艂em, ale nie zawsze

Eliding Async and Await : PROBLEM

                    
                        public async Task<string> GetWithKeywordsAsync(string url)
                        {
                            using (var client = new HttpClient())
                                return await client.GetStringAsync(url);
                        }
                            
                        public Task<string> GetElidingKeywordsAsync(string url)
                        {
                            using (var client = new HttpClient())
                                return client.GetStringAsync(url);
                        }
                    
                

Wykona si臋 Dispose w HttpClient wi臋c zwr贸cony Task nie b臋dzie m贸g艂 si臋 wykona膰
blog
Copyright 漏 Cezary Walenciuk

async i await exception

                    
                        static async Task Main()
                        {
                            var task = M2();
                
                            if (task.IsFaulted)
                                Console.WriteLine("Error");
                        }
                
                        static Task<int> M1()
                        {
                            throw new Exception();
                        }
                
                        static async Task<int> M2()
                        {
                            return await M1();
                        }
                    
                

Nigdy nie zwracajcie NULL jako informacj臋, 偶e co艣 posz艂o nie tak
CancellationTokenSource

CancellationTokenSource

                    

                        static async Task Main()
                        {
                            CancellationTokenSource tokenSource = new CancellationTokenSource();
                            CancellationToken token = tokenSource.Token;
                            tokenSource.Cancel();
                
                            var task = await ReadFile(token);
                
                        }
                
                        static async Task<string> ReadFile(CancellationToken cancellation = default)
                        {
                            var t = await File.ReadAllTextAsync(@"D:\numbers2.txt", token);
                            return t;
                        }
                    
                

ValueTask

ValueTask

                    
                        static ValueTask<double> Do(int divideArg)
                        {
                            if (divideArg == 0)
                                return new ValueTask<double>(0);
                            
                            return new ValueTask<double>
                                (Divide(divideArg));
                        }
                            
                        static Task<double> Divide(int divideArg)
                        {
                                double a = 1 / divideArg;
                                return Task.FromResult(a);
                        }
                    
                

Task, Async.
Katastrofalny b艂膮d

Task, Async.

                    

                        static async Task Main()
                        {
                            await What();
                        }
                
                        static Task What()
                        {
                            return new Task(
                                () => Console.WriteLine("1"));
                
                        }
                    
                

Task, Async.

                    

                        static async Task Main()
                        {
                            Task t = What();
                            await t;
                
                            var s = t.Status;
                        }
                
                        static Task What()
                        {
                            return new Task(
                                () => Console.WriteLine("1"));
                        }
                    
                

Task, Async.

                    
                        await Task.Run
                        (
                            () => DoExpensiveOperation(someParameter)
                        );