Stop wasting server resources by properly using CancellationToken in .NET

Поделиться
HTML-код
  • Опубликовано: 27 ноя 2024

Комментарии • 77

  • @nickchapsas
    @nickchapsas  3 года назад +11

    Thanks to Skillshare for sponsoring this video. The first 1000 people to use the link will get a free trial of Skillshare Premium Membership: skl.sh/nickchapsas05211
    This video was recorded before the release of .NET 6 which will bring the ability to reuse a CancellationTokenSource, which means that you won't have to dispose it. That being said, I did not want include that in the video since .NET 6 it is still not finalized.

  • @Jonathan_Henderson
    @Jonathan_Henderson 3 года назад +18

    As a C# Dev your videos are extremely helpful. Thanks for your hard work.

  • @danspark
    @danspark 3 года назад +29

    TaskCanceledException inherits from OperationCanceledException, so you only really need to catch the latter.

  • @klightspeed
    @klightspeed 3 года назад +14

    TaskCanceledException is a subclass of OperationCanceledException, so catching the latter will catch the former.
    On disposing of the CancellationTokenSource, it can only safely be disposed if there are no remaining cancellation tokens hanging off it, and is only required if it is not going to be cancelled. Calling Cancel on the CancellationTokenSource does the same cleanup as calling Dispose, without risking an unexpected ObjectDisposedException when something tries to use a CancellationToken linked to it.

    • @warrenbuckley3267
      @warrenbuckley3267 3 года назад

      Glad I scrolled down I was about to say the same thing.

    • @quain24
      @quain24 3 года назад

      Explicit disposing of CancellationTokenSource is required only when using CreateLinkedTokenSource, or if you're using the CTS' timer functionality as far as I know.

  • @co2boi
    @co2boi 2 года назад

    Good stuff, Nick. It's worth noting that, when working with Azure Functions, there are 2 potential cancellation tokens. One from the caller and one from the Host (APIM). In which case you can use a LinkedTokenSource.

  • @ilyakurmaz
    @ilyakurmaz 3 года назад

    Thank you for the video. This approach was extremely handy when I worked on file uploading/downloading. Implemented TaskCancellation approach with a middleware.

  • @AngusMcIntyre
    @AngusMcIntyre 3 года назад +12

    AFAIK, we should be catching OperationCanceledException. It will be raised in some scenarios, like a call to CancellationToken.ThrowIfCancellationRequested(). OperationCanceledException is the base class, and will be emitted in all cases of cancellation.
    Inheritance: Object -> Exception -> SystemException -> OperationCanceledException
    Derived: System.Threading.Tasks.TaskCanceledException

  • @thibaudgalland1524
    @thibaudgalland1524 3 года назад

    Way clearer now ! thank you so much Nick for your videos

  • @matthewtrip2124
    @matthewtrip2124 3 года назад +13

    No one has explained CancellationTokens as well as you have

  • @spuriustadius5034
    @spuriustadius5034 3 года назад +12

    Thanks Nick!
    In the Postman example, you hit a "cancel" button which somehow simulates closing the browser, right? What if you wanted to have a "cancel" button on your webpage? How would you trigger the cancellation in a web app without closing the browser? In other words, if you wanted to provide a way for a web user to cancel a long calculation they had already started, how would you do that? It's clear how to do it in a console app, but in a web app you have to worry about which httpcontext, right?

    • @nickchapsas
      @nickchapsas  3 года назад +3

      Yeah the way I imagine it (and I haven't tested it) is that you would keep track of the request in the pipeline and have a way to trigger the CancellationToken in some manual way

    • @iurynunesamicussi5147
      @iurynunesamicussi5147 3 года назад +3

      I was asking myself the same question. Would be cool to see this example done both front-end and back-end code.

    • @ArgeKumadan
      @ArgeKumadan 3 года назад +3

      @@nickchapsas i've tested it before. For each request that is aborted browser tries to stop the socket connection gracefully. But in case of it can't do it and if somehow connection closes the framework passes that token. This applies for both scenario.

    • @maheshk2451
      @maheshk2451 3 года назад +3

      One way to cancel from frontend is using axios, i used it in my react application where you can cancel your requests any time. Type ahead search is a good example.

  • @joaonadais923
    @joaonadais923 3 года назад

    This was a great explanation! Thanks a lot for the video!

  • @Tsunami14
    @Tsunami14 3 года назад +11

    I'm a bit confused on your usage of Dispose(). The method doesn't "own" the CTS (it was passed in), so shouldn't it be left up to the owner to determine when it's done with the CTS resource and when to dispose of it?

    • @nickchapsas
      @nickchapsas  3 года назад +6

      Correct. That was just an example when you own the CTS

  • @Masterrunescapeer
    @Masterrunescapeer 3 года назад

    Interesting video, in our case we ended up not implementing it after seeing that most immediately made the request again after cancellation as it was usually an accidental navigate away and all requests end up cached in Redis anyways, there's more than enough cache that DB doesn't get hit that hard, DB is way over-provisioned for when reports are generated.

    • @AvenDonn
      @AvenDonn 3 года назад

      That makes sense in your case, but not all cases are like this.
      For example, I work on digital printing presses, physical machines. A cancellation might be the operator cancelling a "get ready" operation which involves a lot of moving parts, liquids, and electricity.
      We very much don't want to finish the "get ready" anyway, especially if the "get ready" is being aborted because they remembered they need to replace a part for example.
      So it's important to be mindful of what cancellation means and what saving resources means.
      I think both our notions are important. Don't prematurely optimize and try to save on resources you don't need to, and don't assume there's no need for cancellation

    • @Masterrunescapeer
      @Masterrunescapeer 3 года назад

      @@AvenDonn that's quite different as that's a change state request rather than a fetch current state request.

  • @oleksandrkulchytskyi5970
    @oleksandrkulchytskyi5970 3 года назад

    Great explanation!

  • @santhoshn3766
    @santhoshn3766 3 года назад +1

    Hello, thanks for sharing!!
    Can we use CancellationToken to stop stored procedures execution ?

    • @nickchapsas
      @nickchapsas  3 года назад +1

      You sure can as long as you pass them in the CommandDefinition or whichever means your library allows

  • @mirata9
    @mirata9 3 года назад

    I've seen technical explanations of cancellation tokens before, but no one has really put it in the context of saving resources - which is a 'super' important thing. Great vid.

  • @DoorThief
    @DoorThief 3 года назад +2

    I'd like a video in Funcs and extension methods!

  • @ThreeHubs
    @ThreeHubs 3 года назад +21

    hi nick. IdentityServer4 videos will be perfect if you create

  • @MaximGorbatyk
    @MaximGorbatyk 3 года назад

    Awesome video! Thanx

  • @ilankhirin3678
    @ilankhirin3678 3 года назад

    Great video!

  • @nayanchoudhary4353
    @nayanchoudhary4353 3 года назад

    C# can learn something from Kotlin - learn coroutine, and avoid checking tokens.

  • @rawanabodyak8658
    @rawanabodyak8658 Год назад

    Thank you for explaining that .
    is it worth adding the cancellation token if I'm just get small amount of data , like on user info ?

  • @moab5102
    @moab5102 3 года назад

    Thanks Nick,
    Awesome video as always, I have a question how do you send a cancelation token from javascript,
    suppose you have a long running ajax call and a button to cancel, how do you send the token or notify the controller that the operation was cancelled.

  • @tantruongthe-z7o
    @tantruongthe-z7o 4 месяца назад

    i have a question. It is mandatory to pass token from controller to repository, it there any way shorter because i want to use them in repo only ? I found a suggestion that use addScope(). It will be injected to repo instead, do you have any suggestion or any solution for this ?

  • @marcusvmgg
    @marcusvmgg 3 года назад

    hey Nick would it be possible to set a timeout at the Cancellation Token used as a parameter in the controller?

  • @darklen14
    @darklen14 2 года назад

    What about an API application. If the call is taking a long time. Do you set up cancellation token in the app connecting to the api service and then pass it to that api service? Or when the app is running and the user closes the page and cancellation token is only set up in the api endpoint it will suffice?

  • @ronosmo
    @ronosmo 2 месяца назад

    Can you pass a cancellation token to a separate executable?

  • @ArgeKumadan
    @ArgeKumadan 3 года назад

    Good explanation, thanx. But,
    What if we don't have a some kind of loop? we can't use while (!cancelled)
    Should we just put 1 of 2-3 lines if(!cancelled) ?
    Let's say i have 10 methods call in 1 method? should i just wrap those calls as if(!cancelled) ??

    • @nickchapsas
      @nickchapsas  3 года назад

      Depending on what those method do and if they support CT you can cancel early

    • @ArgeKumadan
      @ArgeKumadan 3 года назад

      @@nickchapsas no, let's say it's a CPU bound operation and not a task. Should we wrap them inside of a Task.Run?
      Thanks for the reply by the way.

  • @kunaldedhia5502
    @kunaldedhia5502 3 года назад

    Is it correct to use cancellation token for "http put", "http patch", "http post", "http delete"?
    Bssically i would like to know what all http methods can implement cancellation token in web api?

  • @jinalpatel9154
    @jinalpatel9154 3 года назад

    For the example let's assume that inside while loop you wait for some external event and then you cancel token source outside so I think in this case it still wait for that external event to receive then it process get cancel. Right ?

    • @nickchapsas
      @nickchapsas  3 года назад

      Depends on the implementation. It can pop on the spot as well depending on where you passed the token

  • @shekharkumar-il1jz
    @shekharkumar-il1jz 2 года назад

    So I have a situation where I found that an API keep running due to incorrect implementation of do while loop. Can this canclellationtoken will work in that situation also. Like I can set timeout for cancliation token for 5 seconds and it automatically stop/kill those threads used by it?

  •  3 года назад

    Great explaination. I'm missing the part where a method is declared with a default cancelation token. eg: public void DoAsync(CancelationToken cancel = default).
    Where is the default CancelationTokenSource

    • @arthursoares610
      @arthursoares610 3 года назад

      Default Just creates a cancellation token that is never cancelled. I do not recommend using that is you really want tasks to be cancelled

  • @scott98390
    @scott98390 3 года назад

    Should you really be Disposing the CancellationTokenSource? If it was passed in, it was created somewhere else, and might need to be used further. I agree that if you create it you should dispose of it, but can you explain disposing in this instance? I feel like you should wrap the creation in Main() in a using{} block, rather than dispose in ExampleWithLoop

    • @nickchapsas
      @nickchapsas  3 года назад

      If you control the CT flow end to end then yeah you should. If you use a token that you didn’t create then no

  • @thethomasproject
    @thethomasproject 3 года назад

    Nick, I do have a question for you. What's the best method to handle a cancellation token when the request was a database write that could be more than one write to complete the transaction? Seems once this gets started, cancelling it could put the database into a bad way. Your thoughts?

    • @nickchapsas
      @nickchapsas  3 года назад

      If you pass the CT in a transaction execution CommandDefinition the execution will be cancelled and the transaction will never be commited and get rolled back instead.

  • @gabrielcostin8867
    @gabrielcostin8867 3 года назад

    I have a question here regarding to properly using CancellationTokens. So I tried on my own using it but when trying to call the API endpoint via ajax call the cancellationToken is automatically triggered after like 1 minute, is there any way to stop doing this and actually wait for the response?

  • @Srhyle
    @Srhyle 3 года назад

    This is what I've been waiting for coz I don't know what the hell I'm using those for. 😂

  • @diegoronkkomaki6858
    @diegoronkkomaki6858 3 года назад

    Going to implement the cancellation token in my .NET Core web api controllers now.
    Question though. How should I implement the CancellationTokenSource in my client applications (Blazor WASM in my case)? Do I register a singleton CTS in the DI container and inject that into my blazor components/pages or what is the best practice approach?

    • @nickchapsas
      @nickchapsas  3 года назад

      It’s very likely that Blazor has built in CT support. I would check that first. If not then you would need to register it as scoped. That being said you might wanna leave the cancelling on the server only since the client can make many actions anyway

    • @diegoronkkomaki6858
      @diegoronkkomaki6858 3 года назад

      @@nickchapsas Oh, right.. wait. I might still be a bit confused. If, for example, the controller's GET method takes a cancellation token as a parameter, is the token then provided by the client in the GET request? Surely not, since you'd have to send the CT object as a serialized object in the request body? What then actually triggers the CT? I was somehow thinking there'd be a "Cancel" button in the Blazor web site which would cancel the long running api call (pretty much like pressing C in your console application example) but now Im starting to think that's not how it's supposed to work in web api's or even possible.

    • @nickchapsas
      @nickchapsas  3 года назад

      I’m gonna be honest, I don’t know exactly the technical trigger for the cancelling of the request but client and server are completely separate. I would have to take a lot at asp.net core’s source code

    • @diegoronkkomaki6858
      @diegoronkkomaki6858 3 года назад

      @@nickchapsas reading a bit about this, it seems that from the clients (browser) point of view, cancelling is regarded as refreshing the web page or pressing the stop button while the page is loading (waiting for data from the API server). Somehow, the browser and web api handles these under the hood and triggers the cancellationtoken.
      So the client side code actually doesn't have to implement any kind of CTS to pass tokens to the web api.
      I initially thought (mistakenly) that it would somehow be possible to create a "Cancel" button on a web page that would cancel any previous calls to a web api. I have worked with cancellation tokens in my desktop apps but never really thought about how they would work in web apps.
      The links below cleared this up for me. And thank you Nick for taking time to reply.
      stackoverflow.com/questions/19010856/should-we-use-cancellationtoken-with-mvc-web-api-controllers
      andrewlock.net/using-cancellationtokens-in-asp-net-core-mvc-controllers/

    • @ilh86
      @ilh86 3 года назад +1

      @@diegoronkkomaki6858 The client and server side are separate but work together in a sense. You can pass a cancellation token to HttpClient methods which will cancel the client side of things and the server side should then recognise that the client isn't listening anymore and cancel it's own token that Nick shows in the video. In Blazor I create a CTS in the component and pass the token to the HttpClient call. In the dispose method of the component I call cancel on the CTS so that if the user navigates away from the component (which disposes it) before the request comes back it is cancelled but you could hook it up to a button click or any other user interaction you want to cancel it. If you do it as a singleton in DI then you will only be able to use it once as once it's cancelled it's essentially finished with.

  • @clashclan4739
    @clashclan4739 2 года назад

    How about browser(angular) and http client

  • @amjadhossain7114
    @amjadhossain7114 3 года назад

    @Nick can you show how to use cancellation token with .NET core Web API and MediatR. Or a little bit insight? MediatR handler method has a cancellation token parameter but how to pass controller method cancellation token to the handler?

    • @nickchapsas
      @nickchapsas  3 года назад +1

      Depends on how the flow begins. If it’s in a web api context then you can get it from the controller. Just add it as a parameter in the action and it will magically be there. After that just pass it down

    • @amjadhossain7114
      @amjadhossain7114 3 года назад

      @@nickchapsas thanks, got it man

  • @yoshkoneski
    @yoshkoneski 3 года назад +4

    Hi Nick, can u make a playlist videos that build start App complete with management menus, jwt api, authentication & authorization, additional userClaim for example: userCompany, userId,UserFullName, userRoles(multiple role per User)
    Registration & login auth using google
    Thanks

    • @gustavnilsson6597
      @gustavnilsson6597 3 года назад +1

      I'm pretty sure he has already done that more or less

  • @sebastianp.r.gingter1936
    @sebastianp.r.gingter1936 3 года назад

    Hi Nick, I tried to reproduce that, but it seems I can't make it work. I cancel the request, but the first DB query isn't cancelled - it simply runs until it finishes. So when I cancel after a second, the cancellation is still detected only after the first query is finished, like 6 seconds later. So in fact it doesn't matter if the cancellation token is passed to the CommandDefinition or not: the actual DB query won't be aborted. What did you do to actually cancel the currently running Db query?

    • @flybyw
      @flybyw 2 года назад

      bug of your DB driver?

  • @lucasdluengo
    @lucasdluengo 3 года назад

    I tried this in an Azure function HttpTrigger, using the req.HttpContext.RequestAborted token... but it never gets triggered. Anyone knows why that may be so?

    • @nirushdeveloper5148
      @nirushdeveloper5148 3 года назад

      Hi Lucas,
      Were u able to get it done? For me it triggers to the azure function. But canceled exception is not caught in the calling method unless we use a loop. Any ideas?

    • @lucasdluengo
      @lucasdluengo 3 года назад +2

      @@nirushdeveloper5148 Yes, but it was not a problem with azure. it was a proxy for my SPA that was not propagating the cancellation. And answering your question, yes. The ThrowIfCancellationRequested only is evaluated the moment you call the instruction. Is not something that keeps checking and throws an exception if at any point you cancel the request.... disappointning, but reasonable.

    • @nirushdeveloper5148
      @nirushdeveloper5148 3 года назад

      @@lucasdluengo Thank you very much for your reply. Will find a way to resolve this.

  • @clearlyunwell
    @clearlyunwell 3 года назад

    👍🏽

  • @mikedensem
    @mikedensem Год назад

    Slow down dude...