8 await async mistakes that you SHOULD avoid in .NET

Sdílet
Vložit
  • čas přidán 10. 05. 2024
  • Become a Patreon and get source code access: / nickchapsas
    Check out my courses: dometrain.com
    Hello everybody I'm Nick and in this video I wanna talk real world mistakes that you might encounter regarding await async. It's an interesting topic that many people tend to get wrong and this comes down to how Microsoft handled the original rollout of the feature. In this video I will go through 8 real world scenarios of how it can be done wrong and talk about how we can fix them.
    Timestamps:
    0:00 - Intoduction
    1:19 - Once async always async
    2:46 - Async void is BAD
    6:05 - Prefer Task.FromResult over Task.Run
    8:00 - Avoid .Result and .Wait
    9:37 - Prefer await over ContinueWith
    11:19 - Always pass the CancellationToken
    15:16 - Prefer async Task over Task
    17:11 - Don't sync over async in constructors
    Raw coding video: • C# Async/Await/Task Ex...
    David Fowler's page: github.com/davidfowl/AspNetCo...
    ValueTask: devblogs.microsoft.com/dotnet...
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasGitHub
    Follow me on Twitter: bit.ly/ChapsasTwitter
    Connect on LinkedIn: bit.ly/ChapsasLinkedIn
    #dotnet #await #async

Komentáře • 241

  • @RawCoding
    @RawCoding Před 3 lety +103

    Thank's for the mention :) also a very needed video on youtube, well done. One thing I could reccomend is to increase the font on Rider's menu's

    • @nickchapsas
      @nickchapsas  Před 3 lety +13

      You're absolutely right. I tried doing it before but at the time it increase the font on things that I didn't want increased and it just looked odd. Will try to fix that. Thanks for the suggestion!

  • @MrBarralex
    @MrBarralex Před 3 lety +56

    Dude the cancelation token at endpoint lvl was awesome.

    • @daveblack8752
      @daveblack8752 Před 3 lety +5

      Agreed. I'd always wondered how to cancel the backend threads once the client canceled the request. Being able to pass the CancellationToken thru the endpoint answered that!

  • @logank.70
    @logank.70 Před 3 lety +12

    Something I did in a project when needing a resource loaded within a constructor was to build something that let me lazily load the data within an asynchronous context and await when I need it. It was just a small class built on top of Lazy that I called AsyncLazy. I can still pass in my interface that does the asynchronous call but stuff it inside of AsyncLazy and whenever I need that data I can just do (await _settingsLazy).;
    Plus, in my opinion, I like the way it reads. It tells whoever is reading that piece of code that the data is lazily loaded, cached after the first call, and is done within an asynchronous context.

  • @protaties
    @protaties Před 3 lety +25

    "You should avoid async void". Well that's where the word "avoid" from.

  • @victorcomposes
    @victorcomposes Před 3 lety +14

    Ah man, I should update my personal project... Thanks alot Nick.

  • @fahtihi
    @fahtihi Před 3 lety +12

    Really appreciate the timestamps in the description. Keep up the good work

    • @SixOThree
      @SixOThree Před 3 lety +1

      Chapters in the timeline too!

  • @MINDoSOFT
    @MINDoSOFT Před 2 lety +1

    Love the information shared ! Thank you Nick. Learned a lot from the "Always pass the CancellationToken" and the "Don't sync over async in constructors" !

  • @Reza-zt4sx
    @Reza-zt4sx Před 3 lety +6

    Hi Nick, thank you for your hard work and knowledge sharing here. It would be great if you elaborate about best practices on error handling. It is one on the wide and most useful topics. There are a lot of videos and resources on the internet, but still some of the ideas behind them are not clear for me. Thanks.

  • @metlic5209
    @metlic5209 Před 3 lety +9

    About the last case, when you need to resolve service from DI, there is an article at msdn 'Dependency injection guidelines' with anti-pattern examples where is shown how you can deadlock your thread with an async factory.

    • @pchoudhary
      @pchoudhary Před rokem

      I think simpler thing to do is to initialize the dependency and then inject it.

  • @JohnWilliams-gy5yc
    @JohnWilliams-gy5yc Před 3 lety

    Brilliant gotchas picked.
    Very concise and understandable demo sequencing.
    You are a very good teacher, sir.

  • @leandrowitzke6405
    @leandrowitzke6405 Před 3 lety

    Awesome Nick. Clear and easy to understand. Keep simple. Thanks

  • @codingwithgyver1637
    @codingwithgyver1637 Před 3 lety +2

    Thank you for this video, now I know that async/await in our codebase is really messy.

  • @Mauricio.Solorzano
    @Mauricio.Solorzano Před rokem

    I really liked the way to pass a factory to a constructor that you need to make async. Very enlighting. Thank you Nick!

  • @MohamedOmar-zw2bq
    @MohamedOmar-zw2bq Před 3 lety

    Very nice indeed, especially the cancellation token demo 👍.
    Keep posting more videos about this topic 👏👏

  • @qwerty5689
    @qwerty5689 Před 3 lety

    Thank you so much for this. Best practices vids are the best.

  • @BlazarVision
    @BlazarVision Před 3 lety

    An excellent video going over Async. Lots of great information here!

  • @sujithacharya007
    @sujithacharya007 Před 3 lety +23

    Great content Nick. You should have also shared some insight on 'ConfigureAwait' 😉

    • @nickchapsas
      @nickchapsas  Před 3 lety +23

      I actually intentionally left ConfigureAwait and .GetAwaiter().GetResult() because I will be covering them in a dedicated video, since it's just a big topic.

    • @aboimpinto
      @aboimpinto Před 3 lety +2

      @@nickchapsas Will wait for that videos too!!

    • @oganovdavid
      @oganovdavid Před 3 lety +1

      @@nickchapsas seems like you haven't uploaded that video yet. Please do so, will be glad to check

  • @marcelocarvalho7049
    @marcelocarvalho7049 Před 3 lety

    Amazing! Applying into project right now! 🙏😁

  • @martinprohn2433
    @martinprohn2433 Před 2 lety +1

    Hi Nick, can you explain to me, why should I write "return await new ValueTask(numberToAdd*2);", if I could also write "return numberToAdd*2;" directly. To explain more, we are in an asyc method, so return a value directly is automatically wrapped in a Task (or in this case a ValueTask). So what is the benefit of this additional await?

  • @ivandamyanov
    @ivandamyanov Před rokem +1

    20:46 How do you register a method in DI? I'm probably not searching about the topic properly cause I can't find information about that and I've never done it. Thank you for the video btw, I am really interested in improving my understanding of all the scenarios around async/await and love videos you make about that.

  • @acidhauss7018
    @acidhauss7018 Před rokem +1

    The static async method is really clever, had that problem for years

  • @sdddv
    @sdddv Před 2 lety

    I’m wondering why it's should be preferred since await should be called where result(or exception) is needed. I don’t use async/await for arrow(wrapper) function which is only prepares input parameters. And also use ContinueWith when need to re-cast result without awaiting public Task GiveMeInt() => Task.FromResult(1L).ContinueWith(task => (int)task.Result, TaskContinuationOptions.ExecuteSynchronously);
    Await is very optimized in core, but it’s much heavier in full framework.

  • @vaibhavbrid2133
    @vaibhavbrid2133 Před 3 lety

    Awesome content. Waiting for more on async await.

  • @lnagy88
    @lnagy88 Před 3 lety +5

    async Task is dangerous if it's an event handler, basically the Task object will not be assigned and not GC-ed, thus catching exceptions will not work. async void is the way to go when used in event handlers or expect to not GC.

  • @setsunaes
    @setsunaes Před 3 lety

    I had never seen such an elegant way to handle async calls in a constructor... I will surely use that since this day on. Thanks!

    • @AlexFeature
      @AlexFeature Před 3 lety

      It's not 'really' an async constructor but yeah it's a neat way to handle it :D
      To be honest, though you would want to avoid this sort of stuff anyway just like Nick said.

  • @e-cogs
    @e-cogs Před 2 lety

    Thank you, this is very helpful

  • @L-E-son
    @L-E-son Před 2 lety +3

    RE: "Don't sync over async in constructors" - do you have a clean solution for setting up this initialization pattern when using the Microsoft.Extensions.DependencyInjection namespace (IServiceCollection, AddScoped, AddTransient, etc.) for DI?

  • @casperes0912
    @casperes0912 Před 3 lety +22

    I'm more curious about the async await mistakes I should be making

  • @deathrade0111
    @deathrade0111 Před 3 lety

    Awesome tutorial Nick. One example of something you cannot make async (I haven't been able to). Is event calls on WinForms and WPF. Take the following Load event on a Form or WPF Window. public async void Load() I can do however if I try public async Task Load() it won't compile. Interested to know your work around to make these async. Custom events I can do, as I declare the delegate, but built in ones are tricky.

  • @Arestkaramazov
    @Arestkaramazov Před měsícem

    Thank you so much for this video it has been enlightening!!

  • @mateusferraz4808
    @mateusferraz4808 Před rokem

    @nick You are very nice Guy, I am developer some years, but i am learning to much with you about .NET. Tks

  • @catafest-work
    @catafest-work Před 2 lety

    ... is supported starting with C# 7.0, good tutorial. A good video tutorial will be about your words: " in the dot net scenario there is no way that you cannot await a call ".Thank's for sharing ...

  • @eparizzi
    @eparizzi Před 3 lety +15

    Another confusing topic you should have addressed is the .ConfigureAwait(Boolean) method on Task. Recent DotNetAnalyzers will prompt you to call this method on every awaited task by default. It's not always clear to people whether they can ignore that rule.

    • @EvaldasNaujikas
      @EvaldasNaujikas Před 2 lety +4

      Well, for .NET Core you don't need to use it anymore, unless you're writing a library, because Core itself is not using SynchronizationContext anymore.

    • @menyus777
      @menyus777 Před 2 lety +2

      @@EvaldasNaujikas *ASP.Net core

  • @Vlad-ib6iv
    @Vlad-ib6iv Před 3 lety

    Realy like ur videos about .net. Are you going make video about delegates in c#? More about their usage, cause theory is quiet simple, but there very few good examples of their usage.

  • @info4gourav
    @info4gourav Před 3 lety +2

    I really like nick and raw coading's video...

  • @Roudter
    @Roudter Před 2 lety

    Great stuff...Very useful insights...Thank you.

  • @VinuP2023
    @VinuP2023 Před 3 lety

    Thanks Nick..

  • @christclamard1097
    @christclamard1097 Před 3 lety

    hey Nick, thanks for all those helpful videos. I have a question, what the name of the extension that displays the inline argument or parameters hint your code?

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      Heya. It’s not an extension, it’s a built in feature in the idea I am using, called Rider

    • @pkipChannel
      @pkipChannel Před 3 lety

      Look for ReSharper. Visual studio big extention pack from the Rider authors.

  • @Bourn77
    @Bourn77 Před 2 lety +1

    hi Nick, suppose i have a workflow with async method calls all the way to the repository, is it a good option to use "Task.FromResult" when i have one method which has no awaitable calls to force it async? or is it a better option to make the method simply syncronous?

  • @lollo4711
    @lollo4711 Před 2 lety

    COOL: Enumerable.Empty .. I didn't know

  • @sunilanthony17
    @sunilanthony17 Před 3 lety

    Nick, can you please explain this to me. @ the 11:19 mark, you are awaiting the number from an async call. Won't the next line of code run and fail if the await call takes a while?

  • @DummyFace123
    @DummyFace123 Před rokem

    That async task delay in a gamechanger for task cancelation, used to have to loop 😩

  • @GregWilliamBryant
    @GregWilliamBryant Před 3 lety +1

    Nick Chapsas, in your first example, could you confirm whether awaiting would actually result in the application closing. As the task would pass back control to the main thread and just exit?

    • @nickchapsas
      @nickchapsas  Před 3 lety

      It will completely fall over and stop running

  • @vamsi8669
    @vamsi8669 Před 3 lety

    this is what we are waiting for. Thanks!

    • @TeamCykelhold
      @TeamCykelhold Před 3 lety +4

      You could say we have been...awaiting it....dudu tsss...ok I'll see myself out.

  • @hannasamia6739
    @hannasamia6739 Před 3 lety

    Great Video,
    Short question do you know if they fixed the problem where cancelation tokens don't trigger in IIS?
    Cause it still a problem for me at least with the Controllers token in the API
    Thanks

  • @mAcCoLo666
    @mAcCoLo666 Před 3 lety +1

    I think the possibility of a deadlock is much more dangerous than wasting one more thread. Deadlocks are damn hard to spot and debug. Threads are hopefully quite cheap to create (and you can always revert them back if your performance really suffer from it)

  • @dhammond249
    @dhammond249 Před 3 lety +5

    As painful as it can be, I've definitely found situations where using the async keyword is not realistically possible. In a legacy application this can mean a huge change across a platform. Or for example a legacy 3rd party plugin that has some kind of hooks that don't support async for example
    But yeah... If you're writing a new code base just async all the things and thank yourself later

    • @nickchapsas
      @nickchapsas  Před 3 lety +4

      Legacy applications and await async are the worst possible combination really. You really really wanna refactor some stuff but your hands are tied.

  • @FatihTurkerFatih
    @FatihTurkerFatih Před rokem

    Very well done

  • @Fafix666
    @Fafix666 Před 2 lety

    The problem I see with the last example, is that static methods are a pain to mock in unit tests. Injecting ConnectionFactory and then using it in specific methods to get MyConnection is probably a better approach? Unless the Connection has to be shared between methods, but it'd mean we need atomicity. Does it make sense to have multiple methods in such case?

  • @bongbui
    @bongbui Před 3 lety

    hi Nick,
    when use EF Core with action Insert, Update, Delete data, we should pass CancellationToken?
    Thank you

  • @huyvole9724
    @huyvole9724 Před rokem

    Really Readlly useful !!! Thank you

  • @GazziFX
    @GazziFX Před 2 lety

    7:35 why you awaiting this ValueTask you can just `return new ValueTask(numberToAdd * 2);`

  • @Mooncat25
    @Mooncat25 Před rokem

    Your video is good. But I want to add to the second point which is about `async void`. IMO it really depends on what you are doing and what is the limitation. More specifically, if you are working with APIs that are not thread-safe, and thus you can't use `Task.Run`, then using `async void` is fine, since `await async` without using `Task.Run` runs in the main thread (which is why the exception in the example crashed the whole process).
    I guess this happens more likely when working with game engines whose APIs are most likely not thread-safe.

  • @FarukLuki111
    @FarukLuki111 Před 2 lety

    Thank you for this video! Question: ist the cancellation token global for the whole application?
    Imagine having a windows service that just got the „shutdown“ command!
    Wo alle cancellation tokens fire?

  • @sen.alexandru
    @sen.alexandru Před 3 lety

    I've watched a ton of your videos and after each one I keep saying to myself "how come this guy doesn't have at least 100k subs already?!"

    • @jonathandaniel7321
      @jonathandaniel7321 Před 3 lety

      not many people use dotnet

    • @ihorbond
      @ihorbond Před 3 lety +1

      @@jonathandaniel7321 fake news. a lot of corporations do especially in fin tech space.

    • @ihorbond
      @ihorbond Před 3 lety

      cause he is a Java guy disguised as C# (based on IDE)

  • @styleisaweapon
    @styleisaweapon Před 3 lety

    In VB6 we were told not to use DoEvents because it was bad practice. Now we are told to do it in an even more complicated way in C#/VB.NET, using await and async, a way that doesnt solve any of the reasons we were told not to use DoEvents back then and also has a more limited utility (its all or nothing with async, doevents is any time you want) In VB6 we were also told not to use OnError because it was bad practice. Now we are told to use exceptions, something less capable than OnError (see the distinction between Resume and Resume Next.) Spaghetti in the form of objects is still spaghetti.

  • @th9267
    @th9267 Před 2 lety

    Thanks for video. I have a question about a scenario I need to code. I have a process that will send a request file via SFTP and then I will need to wait for a response file to be created on the ftp server before I download and continue my processing. The response file could appear within 1min to 60mins. If I await this process, is there a way that I can say, give up after 60 mins?

  • @AzureFullstackDev
    @AzureFullstackDev Před 3 lety +1

    good stuff from 00:01 ;)

  • @patrikbak8161
    @patrikbak8161 Před 3 lety +1

    Is it really true that SomeBackgroundThingAsync() is actually a background thing? I'd say it's synchronous until it hits an await and then it depends on the current sync context or task scheduler where the continuation carries on.

    • @nickchapsas
      @nickchapsas  Před 3 lety

      It’s actually a background thing yeah, you can get the source and try it yourself

    • @patrikbak8161
      @patrikbak8161 Před 3 lety

      @@nickchapsas It wouldn't be in a console application.

    • @Xorgye
      @Xorgye Před 3 lety

      @@patrikbak8161 in the case of task.run it is registered in and running on the task pool. But with the void the code gets executed immediately up to an await, but after that... I know it will return to the controller and continue the controllers' path. But that function... It probably gets cleaned up by the GC.
      It would be the same as if you created a task 'dostuff' in a non async function. And in 'dostuff' yielded immediately. Unless you do something with the returned task, 'dostuff' will never continue it's code path beyond the yield.

  • @donjon61
    @donjon61 Před 3 lety +1

    I liked the explanation for the cancellation token and AsyncInConstructors a lot. I didn't exactly know the reason for the tokens to be there, but it makes a lot of sense that a controller just continues to do what it was asked for.
    I'll probably take the static creation method, too. Quite a nice design.

  • @davidmiko1102
    @davidmiko1102 Před 3 lety

    Hi Nick, I'd like to ask if you are using var just because you do not want to write the type of the variable or are there any other reason for that?

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      Hey, I'm using var because I think that my variable declaration name and value assignment should be more than enough to indicate what the type is. The type itself isn't important to me. I can clearly see what it is from the code without explicitly stating it.

    • @davidmiko1102
      @davidmiko1102 Před 3 lety

      @@nickchapsas Oh, okay, thanks! Something new to me.

  • @prasadhkumarjadhav4066

    I agree about not using continue with on task but What about about await a task and then using "on faulted " to it, like suppose if a method fails we want to log/send email to ...is that ok?

  • @dracla26
    @dracla26 Před 2 lety

    Task.FromResult Nice touch!

  • @Daniel-yl5fi
    @Daniel-yl5fi Před rokem

    Hi Nick,
    How do you pass cancellationToken to Task.WhenAll()?

  • @JeanGilbertLouisAriose

    Great video!

  • @NergalDaimonoz
    @NergalDaimonoz Před 2 lety +1

    The part at 5:53 is very confusing to me. Why is wrapping the code from SomeBackgroundThingAsync in a try-catch which re-throws, magically making Task.Run aware that an exception has been thrown ?
    When you say at 5:26 "there is a way to change this, so it throws an UnobservedTaskException", have you done this on the side without showing it between your run at 5:12 and 5:53 ?
    I tried in a sandbox to simply switch between try-catch and not try-catch, but the result is the same : Task.Run wil fire-and-forget.

    • @Draekdie
      @Draekdie Před 2 lety

      Task.Run is not aware that an exception has been thrown.
      The exception is simply logged in the catch of SomeBackgroundThingAsync.

  • @LuxDefensor
    @LuxDefensor Před 3 lety

    Hi, Nick! Thanks for the video. Can I ask you a probably dumb question? You see, I have this problem with async/await in WPF if I try to implement MVVM pattern. Turns out, in a view model properties can't be async. I looked it up on stackoverflow, but their solution is a bit too complex for me so for now I simply either go synchronous or don't do MVVM. But I'm pretty sure there must be some simple and correct way of doing this, which I don't know because I'm self-taught and lazy. After watching your video I thought, this is the person who can help me or at least point in the right direction. Thanks in advance.

    • @jessicafrankston7155
      @jessicafrankston7155 Před 2 lety

      I do this by having a base ViewModel class that implements the INotifyPropertyChanged, and that gets an Action injected that it can call to actually notify. In unit tests, injected Action just runs (whatever....), in real code, the injected Action conditionally invokes (CheckAccess/BeginInvoke) on the Dispatcher (of the window that did the dependency injection at startup). No async/await, though. Needs to use Tasks. Any better ideas to actually go async, appreciated.

    • @mariocamspam72
      @mariocamspam72 Před 2 lety

      @@jessicafrankston7155 You don't have to implement INPC manually in 2022; It's more error-prone and results in massive boilerplate blocks. Use the CommunityToolkit and inherit from ObservableObject. It also contains source generators accompanying the [ObservableProperty] attribute.

  • @TheRealRslive
    @TheRealRslive Před 2 lety

    Does value task still uses the threadpool ?

  • @TheZubass
    @TheZubass Před 2 lety

    Hey, what is the var:type extension?

  • @zitronenmelisse3
    @zitronenmelisse3 Před 2 lety +1

    Actually in the async void is bad example it is not the Task.Run that causes the process not to die but changing the return type to Task and what that does to the method behind the scenes.

  • @ArgeKumadan
    @ArgeKumadan Před 3 lety

    How about using using(idisposible) on async tasks.
    And on your last solution: after i've done what u say, now i cant use ioc container to create instence of SomeService. What am i supposed to do now? I wanna inject SomeService to my controller via dependency resolver.

    • @FilipCordas
      @FilipCordas Před 3 lety +2

      They added await using in c# 8. As for async in the constructor David Fowler recommends doing your async initialization in IHostedService before the app starts, for lazy initialization you can write a filter or middleware that will run your init logic before the request then just inject things a usual.

    • @ArgeKumadan
      @ArgeKumadan Před 3 lety

      @@FilipCordas what u r saying sounds really good, but first we need to understand the concept. First we must understand what happens if we don't do it, what does it couse bla bla bla.

  • @arthurmelo88
    @arthurmelo88 Před 3 lety

    How can I inject async connection on my controllers contructors? I cant use this static approach on my controllers that extends ControllerBase

    • @nickchapsas
      @nickchapsas  Před 3 lety

      You can do that by creating a service, initialising in that new service and then injecting it in the controller

  • @stephenyork7318
    @stephenyork7318 Před 3 lety

    So what do you do with event handlers in desktop applications that have to be async void?

    • @nickchapsas
      @nickchapsas  Před 3 lety

      I don't think that exceptions in async void desktop app handlers can cause the app to crash so that usecase would be valid. That being said, I don't have enough experience with desktop apps so I am not aware of any alternatives

    • @gnack420
      @gnack420 Před 3 lety

      Event handlers are mentioned by Microsoft explicitely as being an exception to the "avoid async void" rule, so feel free to use 'async void' for those.

    • @LeMustache
      @LeMustache Před 3 lety

      Just as the second Nick said - this is one of the reasons (if not the only one) you can even use void as return type for async functions. Because of event handlers.

  • @internetmarketingog2268

    How would I use await inside a catch statement in vb.net?

  • @lightandtheheat
    @lightandtheheat Před 3 lety

    Just a note with the last one. Changing it into a factory makes DI way more complicated. An alternate solution that works fine is to offload your async construction calls into an async Initialize method. In the constructor, call your Initialize method and assign its resulting task to an instance variable. Then in your async methods that depend on the initialization to be completed, "await _initializationTask;" at the top. No need for factory, still works great with DI, and you can call async stuff safely from the constructor.

    • @nickchapsas
      @nickchapsas  Před 3 lety

      I think I don’t fully get it. How do you asynchronously await from the ctor?

    • @lightandtheheat
      @lightandtheheat Před 3 lety

      @@nickchapsas You don't. You await the task that you've stored in the instance variable from the start of any methods in that class that are dependent on it, by which time it would have likely completed anyway.

    • @nickchapsas
      @nickchapsas  Před 3 lety

      @@lightandtheheat Oh no I would never do that. I like deterministic behaviors in the software I write.

    • @lightandtheheat
      @lightandtheheat Před 3 lety

      @@nickchapsas I think CZcams is deleting my comments because of a pastebin link, so just in case, here's a pastebin id for an example: "Dask3TsG". It's still deterministic, just asynchronous-- the outcome is the same each time (deterministic), so long as you have a call to await the initialization task. An example use would be if you need to add a client certificate to an HttpClientHandler at construction, but need to fetch the certificate asynchronously.

    • @nickchapsas
      @nickchapsas  Před 3 lety

      @@lightandtheheat I really don't like this. If this thing is needed in multiple methods then you're literring every method with a state machine and an awaitable context that could be completed. You're wasting both memory and time and you're leaking a class level concern on a method that shouldn't know about it.

  • @iamintosomething
    @iamintosomething Před 3 lety

    Very useful video

  • @parsamehdipour2473
    @parsamehdipour2473 Před 3 měsíci

    Nice🔥

  • @matthiasschuster9505
    @matthiasschuster9505 Před 3 lety

    Did you check if they also count for F#, or is this just for C#?

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      Since these are CLR specific, they should stand true for F# as well

  • @theMagos
    @theMagos Před 3 lety

    The cancellation token should be used with care. Canceling a save operaton half-way through could leave your database in a undesirable state (half-saved objects).

    • @nickchapsas
      @nickchapsas  Před 3 lety +5

      Ideally all your db operations in a since call should be atomic. Breaking them down to multiple calls or having them be non-transactional is dangerous no matter whether you use a cancellation token or not

  • @fullmoonyeah1180
    @fullmoonyeah1180 Před rokem

    if an async operation doesnt return any result, just use fire forget. is it correct?

  • @xybersurfer
    @xybersurfer Před rokem

    how would you avoid "async void", when you have to do something async in a typical event handler?

  • @charrystheodorakopoulos4843

    Κάνε ένα και για την ConfigureAwait για το λαό σου.

  • @ziia0528
    @ziia0528 Před 2 lety

    9:20 how a IValueConverter method could be async?

  • @SECourses
    @SECourses Před rokem

    In first case it is terminated because still you are running in the main thread. Async Await is not by default running in sub threads / tasks. Here my async await video : czcams.com/video/I4cnX_odC1M/video.html . continuewith is good if you are not awaiting the task result.

  • @Any1SL
    @Any1SL Před 2 lety

    Steven Cleary has a few amazing blogs on this.

  • @user-tk2jy8xr8b
    @user-tk2jy8xr8b Před 2 lety +2

    Making
    Task F() { using var g = G(); return H(g); }
    instead of
    async Task F() { using var g = G(); return await H(g); }
    is a straight way to get a disposed object accessed

    • @josephmoreno9733
      @josephmoreno9733 Před 2 lety

      In that specific case, the async/await must be used or pass a delegate to G() inside the task (or call the G() directly in the task). Always is better use the using keyword inside the task.
      I think the async/await overhead can become significant. However I return task if and only if certain 'rules' are met:
      * The method that returns the task has the same type of returned task or is a task without result.
      * The method that returns the task only executes that statement.
      * The method that returns the task executes that statement at the end and is the only asynchronous call one but, the parameters for this task must not be invalidable (collectable or disposable or mutable outside the task) in the lifetime of the method execution, that includes delegates or tasks (which should be awaited inside the returned task) as parameters.
      * The method that returns the task must uniquely choose from a finite set of tasks of the same type which one to do based on runtime conditions.
      Any violation to this 'rules' implicates use async/await.

  • @Zapo9668
    @Zapo9668 Před rokem

    Very cool video

  • @MiceDevelopment
    @MiceDevelopment Před 2 lety

    for fire and forget/return avoid configureAwait(false) will do isn't it ?

    • @nickchapsas
      @nickchapsas  Před 2 lety +1

      This really depends on the sync context of your app. In .NET Core you don't need it.

    • @MiceDevelopment
      @MiceDevelopment Před 2 lety

      @@nickchapsas ouhhh okayy thank you nick ! :)

  • @jaanrett
    @jaanrett Před rokem

    In a scenario where you override a method that does not have async in the signature, how do you await without an async void?

    • @nickchapsas
      @nickchapsas  Před rokem

      You can't

    • @jaanrett
      @jaanrett Před rokem

      @@nickchapsasI had written a game for Xbox live indie games back in 2010 before async/await with c# and xna, and that was probably around the time I also stopped working professionally with c#. After about 10 years I wanted to get back into .net and c# and thought I should port my game to monogame, and uwp to make it work on both windows and newer Xboxes.
      That's where I had to figure out this new to me async/await. I struggled the most with this one aspect, everyone telling me to avoid async void, and not knowing a better way to integrate async apis into a framework that doesn't support it, specifically update/draw functions from the monogame/xna.
      Anyways, it would be great if you made a video about that kind of real world integration issue.
      In any case, I enjoy your content and your knowledge. Keep up the good work.

  • @CS-eh8eo
    @CS-eh8eo Před 3 lety

    Nice content, do you know anyone similar who does kotlin ?

  • @kaisersolo76
    @kaisersolo76 Před 3 lety +3

    Always pass the CancellationToken - while I do agree with this in general , they should be employed tactically.

    • @nickchapsas
      @nickchapsas  Před 3 lety +3

      Yeah I forgot to mention that if you don't want that process to be cancellable then you shouldn't be passing the token. Something like an asynchronous email sending for example.

    • @kaisersolo76
      @kaisersolo76 Před 3 lety

      @@nickchapsas great stuff regardless, keep it coming!

  • @stevehoff
    @stevehoff Před rokem

    Hmmm I was taught, by MS that you should not always await every method that returns a task because that's a ton of overhead. If you are not doing something with the task return value there is no need to await. This creates state machines which adds not only CPU cycles but also the memory your app uses.
    Please explain why you think every task method should be awaited.
    Thanks!

    • @stevehoff
      @stevehoff Před rokem

      I should add that yes, you should eventually await the the stack and can even mix awaiting and not awaiting in a single call stack.

    • @lawrencetsang3368
      @lawrencetsang3368 Před rokem

      I may add,
      that RUN TASK, thing,
      It is to wrap an otherwise NOT await-able method, for UWP and Windows Sdk App. (WPF programmer, don't know UWP, will be confused.)
      Example, Windows Sdk App, in side a converter -> will crash, if you copy a WPF converter and try to use on "IT":
      you need to do this:
      try
      {
      Task.Run(async () =>
      {
      var stream = await file.OpenReadAsync();
      dispatcher.TryEnqueue(async () => await BI.SetSourceAsync(stream));
      });
      return BI;
      }
      ___________
      in other words:
      If you have a BIG method coded with WPF, do not want to recode it for UWP/WAP,
      That, run-task thing, is very useful.
      Another Example, with WPF, fetch SQL return from local database, it will wait and blocked, unit it is COMPLETED.
      Copy that block of code to UWP, it may not work, or crash.
      Because? the method will return immediately, before the result is completed.
      FIX? -> that run-task await thing.

  • @ruslanbocharov
    @ruslanbocharov Před 3 lety +5

    catch (TaskCanceledException) when (cancellationToken.IsCancellationRequested)

  • @ivandrofly
    @ivandrofly Před 3 lety

    good content

  • @PaulBilton
    @PaulBilton Před 3 lety

    Rather than using .Result on the end of your await calls should you not use .ConfigureAwait(false) ??

    • @nickchapsas
      @nickchapsas  Před 3 lety

      .NET Core doesn’t have a sync context so it doesn’t matter, but in that specific example it wouldn’t matter even if there was one because the task has completed and we can get the result as a property

    • @daveblack8752
      @daveblack8752 Před 3 lety

      If the code is guaranteed to only run in a .NET Core app, it can be omitted as .NET Core does not have a SynchronizationContext. However, if the code is built as a library (maybe it's compiled under .NET Standard) and that library might be used by an app that is running on .NET Framework, it should be added since .NET Framework does have a SynchronizationContext.

  • @unnilunnium101unknown8

    Which IDE is he using?

  • @UntakenNick
    @UntakenNick Před 3 lety

    What's with the "new Exception(message: "bla.." I had never seen that type of declaration before.

    • @michielarkema
      @michielarkema Před 3 lety

      You can throw your own exceptions.

    • @UntakenNick
      @UntakenNick Před 3 lety

      @@michielarkema I know, but I would have written it
      new Exception ("Message..")
      or
      new Exception () { Message: "Message.." };

    • @michielarkema
      @michielarkema Před 3 lety

      @@UntakenNick The first one.

    • @UntakenNick
      @UntakenNick Před 3 lety

      @@michielarkema But in the video he writes
      new Exception(message: "Message..")
      in lower case and inside the parentheses, which is what my comment was about.

    • @michielarkema
      @michielarkema Před 3 lety

      @@UntakenNick oh that's just syntax highlighting from the ide.

  • @PaulSebastianM
    @PaulSebastianM Před 3 lety +1

    9:10 Well, no. If you're implementing a foreign Interface and that doesn't support async methods, and you need to await async methods inside sync methods of that Interface, there's no other way but to force synchronisation.

    • @nickchapsas
      @nickchapsas  Před 3 lety

      I have never used a .NET library in the past 5 years that either isn’t purely async or doesn’t over both a sync and async alternative for its implementation. I am happy to take a look at an example and offer an alternative though

  • @jradplowman
    @jradplowman Před 2 lety

    I see so many of these in our legacy code base... Looks like it's time to refactor 😝

  • @watchchat
    @watchchat Před 3 lety

    Nice