Worker Services in .NET Core (Background Services)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up youtube in today's video we're going to be looking at workerservices.net core sometimes they call background tasks sometimes they call background workers background services i'm going to call them worker services because that's what the visual studio project template is about we're going to be looking at some low-level stuff i'm going to explain to you what and how about the worker services we're going to build our own worker service from scratch as well as from the public templates and we're also going to be building uh a worker service that's more real world it's going to be listening to in this case rapid mq q to receive messages and process messages i'm going to take that same worker service and host it as a windows service that can be also a daemon on the linux linux platform and can also be hosted from within an asp.net core application so we're going to take this thing through various spaces all right so let's get started what is this whole thing there's the idea of an application and then there's an idea of a hosted service so asp.net core is a hosted service within an application all right in other words there's an application that's running and then that application hosts other services in this case it's asp.net or if it's signalr the same idea there's a hosted service where the hostage service's lifetime is essentially controlled by the application the main thing that's running that controls the lifetimes initiates the service and also gives it a way to gracefully shut down the service before this whole idea there was always a feature of a possibility to create your background tasks or background services but the main problem was that they would not have a way to gracefully shut down things so they would just be killed or kind of left often depending on how you implemented it so the idea with the hosted service is that they are controlled by the lifetime of the application that's running them and the application in turn will start it and stop it when it's shutting down and give the opportunity to your background services to gracefully shut down any dispose of various things close off files or flush files and you know dispose of the handles stuff like that so prior to net core 2.1 or 2.2 we used to have the notion of iweb host these were hosted applications that were very web specific they dealt with server hp http servers and such since 2.1 or 2.2 we now have ai host that is independent of web things you can certainly make web call http client calls from your hosted server worker service but it's not tied to the rest of the asp.net core infrastructure with regards to web applications you do get access to the configuration system the dependency injection system the logging system and things like that that are independent of web but you don't get to you don't need to have the whole kind of dependency on the web infrastructure with an ihost the basic idea then is you host your hosted service in an application it's really any class that implements the i hosted service interface we get a base class that has some basic implementation for i hosted service that you could use that provides you some with some infrastructure or plumbing for tasks but basically you can build your own and we will be doing that in in today's video as well where we'll use the the basic the base class that's provided to us within the dot net framework but we'll also build our own from scratch just to get a sense of you know what does it take and i'll also show you the code of the base class that's implemented in dotnet course you get a sense of what it's doing for us all right and then we're going to take that through spaces and eventually move it to asp.net core application i'll talk about some of the pros and cons when you should i should not do some things in asp.net core applications regards to worker services and sequence matters so you want to be aware of that as well all right so without further ado let's get started with the code all right so i've just started visual studio i'm going to pick a new project and in here i'm going to look for worker and i'm going to pick this worker service template okay this is the dot-net core 3-1 all right so let's look at some of the stuff that's been done for us so here i'm going to look at the the background sorry the program cs file now we've seen this class before it's i mean the the code here before is very similar to what we would see in a asp.net core application which is correct i mean it's almost exactly the same and the reason is that they're both posted services in that sense right the application is a console application in one case is hosting an asp.net core application in the other case it's hosting a worker service application there are subtle differences where when it comes to the web the method here that's called configure services i think it's called configure web services or something we'll see that it's just that one big difference here a small difference i guess not a big difference here and what is done is it has registered a hosted service called the classes worker right and if you look at the worker class you'll see that it's descending from background service the base class i was talking about this is an abstract class and it has a one method that's abstract that we need to implement which is the execute async and it's called workers so basically what we've done is we've registered as a hosted service this worker and here what they've done some default implementation is that they've got this cancellation token and they're looking you know going a loop here and seeing you while the cancellation token is not has not been requested to be cancelled keep doing this and then here it says you know delay wait for a second and print out this thing using the logger information so this is fairly basic stuff now what might not be clear or the way this has been implemented might seem like what if let's first run this okay sorry let's first run this see how it works just to get a sense of how it works and then i'll start to modify this stuff a bit so if i run this application you'll see that it prints out to the console here every second this output right which is what we were expecting now what would happen considering that this is in a tight loop here in the while loop here what would happen if i didn't have the center tight loop what if i just did one thing and then exited from this loop or essentially had nothing the normal expectation for those of us who've been programming in threads or in windows services and such would expect that as soon as you exit from this method it ends your application that's not true of hosted services remember worker services are hosted services they are not the actual application itself so i'll show you i've commented out the code here i'm gonna run this application and we see nothing happens but the application doesn't actually quit and you can see it's still there this was a bit of a foxing thing for me but once you understand that these are hosted services your worker service is hosted inside of an application like a.net core a console application just like an hsp.net core application is hosted inside of a console application or a signalr application is hosted inside of a console application so because the lifetime is managed by the application the console application it's not going to shut down when the console application is shutting down that's when your worker service will also shut down and we'll see how that happens now next so one of the things we can override or one of the methods we can override here is the startup start async and stop basings we'll override both of them just we can see the sequence in which these things happen okay so i'm simply calling the base classes methods here now in reality what happens is this base class here the worker service class it calls execute async from startup meaning startup is called by the application that's hosting this application and then the background service based class then calls execute async from its start async method and it kind of waits for that thing to finish and when it comes back to the task it uses that task as a sensor to know whether you're finished your work or not when it comes to the stop async it will then sort of cancel that task and so that you're if you're using that task within your long running process you know now it's shutting down and so you can take measure and shut down your part so there are some things you got to be careful of regards to tasks and cancellation basically need to understand how to use cancellation tokens so that you're playing nice all right so i'm going to just put breakpoints here all right so now i'm going to run this application so first you're going to see it coming into start async right and then start async when it come when we call base that will call execute raising so let's look at that so now we're going to execute async and this as it exits it just waits there right nothing's going to happen it's not going to come to stop we're just going to wait here this is done and we're waiting when we plan to shut down or attempt to shut down the application here that's when it comes to stop and then that's when it shuts down now there's a caveat to that as well which is it's not that much of a caveat it's just something you need to be aware of the main application that's hosting your service will wait only for a finite amount of time on the stop async part so it's got a 10 second timeout sorry five second timeout so in five seconds it's going to kill your application so if you haven't finished off with your clean up process or whatever you need to do with your disposing of things then it takes longer than five seconds your app that that service worker service is just gonna be killed it's not gonna wait for it endlessly now in the documentation they talk about how to extend that time out and they make it sound very simple i have not found a way to extend the timeout for this purpose so i've tried everything you know that i can think of not that i know a whole lot here but besides the documentation i've tried other things and none of it actually works to extend the timeout it works out and it compiles but it doesn't actually extend the timeout so it's not a big deal but something you should be aware of five seconds so i'll show you what how i know that that doesn't extend it because if i come here for example so i run this application right so now it's running now what i'm going to do is when it comes to this top async method here eventually right when i attempt to close this application and it comes to the stop basic method here i'm just going to hold down this breakpoint and then i'm not going to step through and you'll find that the application just shuts down by itself all right after five seconds okay so it's here i'm doing nothing i'm just waiting and at some point five seconds are over and bang done that's that's the thing so even though you might be doing something in this method here but it's longer taking longer than the five seconds it's not going to get give you that more than the five seconds unless you can extend that time if you need it so in case you have to i don't know flush out all the files and make sure all your transactions are committed and various other things that takes a whole lot of time hopefully you don't write that complex code in this thing you may not have five seconds may not be enough but something to know okay now i'm going to instead of using this worker in the background service what if we built our own from scratch all we need is something that implements i hosted service that's it you don't have to descend from this background service even though it's a good thing that we they we have a base class available to us that does some of the basic stuff but we don't actually need to descend from this so what i'm going to do next is going to build our own hosted service that really just got a timer instead of in a loop here like we had in this class here instead of going in a loop you know seeing if this cancellation term was requested we use a timer and fire an event every second and do something in that event all right okay so i'm just going to define a new class in this project it's just a class so i'm going to call it uh timer worker service all right and this thing this class needs to implement i hosted service oops and also needs to implement high disposable okay so if we look at i hosted service you'll see that it has these two methods start async and stop async and i said that earlier that the there is no execute async the execute racing is called by that background service based class from start right so but by default the host resource has no executation it's got to start and stop and these methods are called by the host the application the main application the i host that you're hosting your worker service into or with so that main application calls start and stop when it is started and when it is stopped or is stopping right so that we have to just implement these two methods so let's do less than between these two methods actually also need to implement disposables dispose okay post these things in alpha order i'm not sure that's the best way to do it like my disposal and things to come at the end all right so let's define a constructor and the constructor i want to get a logger so i can log things to the console here so we'll get an i logger of this and we'll call it longer okay and when we start what we want to do is we want to create a timer a dotnet system.threading the timer measures at that time of the i think three at least three times on.net so make sure you use the system.threading.timer that's the one that's thread safe all right so in the start async method we're gonna create an instance of the timer we're gonna set up the period or the the duration for the timer and then we implement that timer event that we ask it to call and do some logging in that and they stop async we stop the timer and the dispose we dispose the timer pretty simple let's do that so here we're gonna have a timer i should probably define this timer hopefully this timer is a system of threading the timer where did it pick it up from yep okay new timer and it takes a time or call back and then there are other overloads here let's take a closer look as the other lowers overlords are taking an optional nullable optional level state and uh due time and period in the form of inch longs or time spans okay so what the heck does a timer call back look like so let's look at that the signature one would think you'd remember all these things but i don't actually remember all these things on the top of my head so okay so it's just a method like a delegate that that has a argument of type object they call a state and it's a void returning method all right that's what we need so we shall define our own method here it could be private that returns a void let's call it on timer that takes uh type object and they call it state the state is a way for you to sort of provide the state from here to the callback so for example if i want to send the cancellation token as part of the state that when i'm in the event i get access to the cancellation token to see if that translation token has been cancelled i can pass that cancellation token as a state now let's just do it didn't want to use that and make it that complicated for now so this will be called on timer right then the next argument is object state so we'll call give it the cancellation token and then let's use the time span version here so the first argument i think is saying the due time so it should be due in after five seconds after creation and then the period of the timer is also five seconds so that's what i'm thinking it's gonna after five seconds it fires the first event i don't want it to fire the event the first event immediately wait for five seconds after it's been created and then father event and over here we just use the logger to log something um log information let me say [Music] called we're not using the thing here but you could have a check to say you know if it's not been cancelled only then do this part all right now in the stop here we need to uh kind of turn off the timer and then get ready to do the disposing the disposing we'll do the timer or dispose it could be null depending on when this gets called let's do that anything else to dispose okay so in here we just need to basically shut off the timer it's not necessary but let's try it so here we can do on change i think it's called change the you know the period and all that and we say um timeout dot infinite so basically the duration is infinite and the period is zero so basically the due time and then don't start forever and the period is zero so it never triggers again you don't want it triggering while it's trying to dispose this thing because it's multi-threaded so you could call this thing while it's trying to dispose over here so you want to first just shut it off i think that's all that is required oh yeah i think we need to return a task see that's complaining here so if you did something asynchronous then we wouldn't have to return a task let me just show you what i mean so if i did let's say task dot delay and as i delete for 100 milliseconds doing some work actual work here and i awaited this [Music] then animate this asynchronous actually you know this is oh yeah so then i don't need to return anything because in asynchronous method a method that's marked with async modify a task return is like a void return you're not actually returning anything you just because you're waiting this method if the method is not asynchronous you'll actually have to return a task it's not some piece of you know like sure it's actually you got it on a task so if i undo this then i don't want this to be a signal since i'm not actually doing anything asynchronous then over here you're saying okay but where okay you're not returning anything so we need to return something here task. complete task okay so we return that and in the dispose here we can also should probably log just to be clear here so let's do this is stop acing called i don't think we'll see any of this stuff and here we'll say dispose called okay so you got our own same thing here we need to return the completed task if you implemented our own implementation of i hosted service and i disposable it's called timer worker service now we're going to register this time over service with our hosting application so that it can host this for us oops and i could need to just repeat it like that and hosted service and give it our timer worker service now both are registered meaning the original worker is also hosted and so is our timer so they're both going to write to the same logger so maybe just shut down one but we can see how it looks could be like a clutter of events one coming every second the one coming every five seconds we actually turned this off for the actual workers that's cool okay there you go so every five seconds we are seeing the timer for this thing and so of course in the other case we don't have let me actually turn this off by on i mean the uncomment of this code so this will come every second it'll be a bit of a clutter but that's fine okay so now around there so remember both the things are being hosted both the services are being hosted so once doing this one every one minute thing and then every five seconds you should get the timer part i'm not sure you will see much that's the on timer event here and so on right so both background services are working perfectly fine independent of each other they just both happen to be writing to the same logger so that could be a bit confusing and they're both hosted by one application so what i'm trying to get across is within a.net core application console application or a host it can host multiple worker services right and that's something you might want to think about from a design standpoint if you're are collecting some applications that require multiple workers services you might want to do that keep in mind that that backgrounds those background services are using the resources of your main application okay that's one aspect the second thing is if you're deploying to the cloud you got this one box with your let's say your application that has these two workers services running in the background in the cloud you typically have multiple instances of your application behind a load balancer as you scale out horizontally your main application these background services are also scaling on that may not be something you want right that's not necessarily it's not always that one-to-one correlation between your application and the background services you probably want one instance of a background service but you want multiple instances of your actual application so that may not work out for you in that sense but so keep in mind that that's very different web jobs are slightly different in that and i think web jaws are retired i'm not sure they've been deprecated i can't be sure but with web jobs you could actually have them hosted separately you know in a separate instance with background services that's not the case because they're running in the context of some applications so if you already have an application in azure let's say that has multiple instances deployed each of those instances have these two background services and they could be competing with each other to do the same thing because each background service is doing the same thing right and the other part to think about is that your applications need or the rate of scale unit of scale is not the same as the services unit of scale so you don't need as many services as as the application devices maybe you need more sources then you need application instances from a scaling standpoint right so you want to consider all of these things but we will see how we can use the same services in an asp.net core application all right so if you get this basic idea of our own hosted service or using the background service class basically that's available.net the next step is to build our own application own service we'd use the background service as a base class but i want something more real well i want to build a rabbitmq listener so then we publish messages and we listen to these messages and make sure we receive them in our workout worker service then we're going to take this worker service and make it a windows service we want to install it in the windows infrastructure as a service it will be a daemon in linux if that was the case and then have it run and see it do the same thing that is basically to see these messages be published and make sure it consumes the messages and does the right thing while it's a service and the reason i'm saying this is that windows services don't have a visual anything you're not going to see it we're going to find a way to determine that it's actually happening all right and once we have that working we're going to take that same application and make it hosted in asp.net core normal asp.net core application right so we'll take the same code base and just basically i'm going to make this in a separate assembly so we can just use to use the same assembly in a web application as well all right so shut this down okay so we don't need this timer one i'll leave it here so maybe when i i'll make this code available on my github so i'll leave all this code here like this and then you know you guys can pick and choose what you want to see in case you want the timer version of it okay let's add ourselves a new project and we'll use a standard library yeah standard class plus libraries.net and we'll call it they have an mq subscriber worker okay now while in the other project a lot of the microsoft.extensions.hosting and a bunch of other newbies were implicitly as part of the project template here we're going to have to implement all of those things or let's reference all those nougats ourselves right so it's going to be a bit rough when we start off so the first thing i'm going to do is i'm just going to call this class um rabbitmq subscriber [Music] okay and this travel inquiry subscriber should be descending from our background service this background service is another assembly um microsoft.extensions are hosting their abstractions okay i thought it was just hostings but maybe okay and then this thing needs to implement the executive sync all right so that's our basic background service and now that we have the service we should be able to register this ramadan queue service with our the console application that we had here the worker service part here so occur then we'll have to reference our library our project reference reference that library from the vocal project worker service application so that over here we could do that in that all right so now the broker service this project is using the rabbit mq subscriber worker from this dotnet standard library project okay and here in the file budget here again i want that logger and stuff so we'll ask for the logger this time it'll be the arrival mq subscriber worker now i'm going to show you our original code that we built a few videos ago i'm going to copy that according here make a few changes yes type okay okay so let's open the other project so if you haven't seen the other this project i'm talking about here that i have an mq message broker projects please take a look at that project there's a series of videos on message brokers i'll put a link to them all over here the code the source code that i'm looking at here also is available in my github so once you go to those videos you'll see the links to the github that contains that so scroll i'm just using the same source code here and i have uh the i want the subscriber so look at this subscriber it's got this uh basic subscriber implemented here but in our case we want a start maybe an execute and a stop so we want to break this down into like different steps where we start we do something and when we stop we do something else right so at the time of starting maybe we should start listening and that the time of stopping we should dispose of our connections and various other things that this rapid mq stuff has over here so essentially what we do is all this needs to be done so after the basic consume we should be disposing of our channel in this case so this should go into dispose for that we need the consumer tag in there so i'm going to copy this code over and then make some changes you know so that we don't lose a dissolve currently in one method we're going to split it up into two different methods that have something the subscriber code and then i'll use the publisher here to publish messages so that the subscriber that we build in our worker service will receive those messages all right so in the execute i'm going to just plonk all this stuff in here right for now it's not going to work out because we don't have rabbit mq so let's even get rabbit mq installed no good install so i have an mq okay that's that so now if we say connection factory oh which project i installed in okay i'm not sure what better than installed in oh i installed in this project i wanted to do in that one so i don't actually need in here but i do need it in here yeah okay eventing basic consumer also this part of the library get rid of all the errors okay now oh encoding also let's put that all right so we're going to need this because these are things that need to be disposed they won't be disposed of course in here they'll be disposed in the in the stop so i need to extract these out and have them as local private members of this class so this is an eye connection and this is in my model so connection is connection and the channel is the model let's do that [Music] [Music] call this channel [Music] all right so then we can pick that out take that out and this channel is everywhere okay another thing is this the the console or right i'm gonna have to modify it to uh the logger so which means we'll use this logger here and we start converting this console.right to using the logger it's a logger dot log information just take all of this stuff here [Music] another thing you want to see is or i wanted to mention was this when you implement that worker the default worker that was created for example and when you start a new worker service project and you get this code created for you right with a while loop and everything basically like this these are two something i implemented okay don't write your code in here in this execution task the idea of or the best practices would be to take your code call it from here so you implement all of your functionality in a separate class or classes and then from here you in turn call executor start and stop don't write the code in here that way you can reuse that class in many other places it's not about reasonability it's about mainly decoupling your worker the actual host if you will from your perspective the background service and the stuff you do in your application right so you can take that and move it to a console application or a web application and so on instead of writing that code kind of right in there so in our case of course because we are now making a separate library here this the rabbit subscriber is just in a class by itself it is a decent background service but it's not so hooked into that that worker infrastructure it is completely separate so now now that we have that uh i'm gonna okay we need to execute so let's do this let's uh oh that connection also is all right so now here once we have this the consumer tag uh what type is this string so i'm just going to take that consumer tag and make it also private member okay and then once you consume um you can convert this to logging you need to take this as the kind of undo the the consume right that's really what happens the consumer kind of block here this event gets fired for every time message is received and when finally this the thing finishes here the application it'll do that this is more like the dispose part so we don't need that we don't need that and here we'll implement the there's the i disposable gun oh stop stop async so here we need to do that so now in the channel and between the channel and the connection i'm going to dispose both of them so the channel once i do that channel.dispose or close i guess we can use and the connection that close there's some sort of a dependency between these two one or the other i guess close but for now you just leave it like that in other words if you close the connection it also builds a channel or something right so but i'm closing the channel first and then closing the connection okay so that's that now this background service is a background service right and so it has the execute async here and it has we implement also the stop async and we call the base classes method here now here what we could do since we have to return a task here we can do the return task or completed task or we could keep it in a loop let me change all these logger sorry about all this time maybe i'll just password it depending on how long this actually takes okay that's that but as you know the execute async doesn't have to wait you don't have to block it in this method for it to continue so just keep running and we do need to return our completed task and then now you might want to do in such a way that depending on this concept the stopping token here you might want to use that token in a loop and say you know while it's not cancelled like do something as soon as it's canceled you can do something else in this method or you just wait do it in the stop async method here which is what i'm doing so then here we should return a task and so that's what we shall do completed task all right now we can register this worker service with our console application which is here i'm gonna already did that okay didn't i did that all right so that's that then let me remove the other this worker i don't i don't want this so right now we're just working with the dividend queue subscriber that's our average mq subscriber class here don't need all these things okay okay so we can put a breakpoint here make sure it starts and that wound okay there it is can i connect to rabbit okay so look as luck had it i had that average this is running in my docker here so if you look at the docker desktop the instances that have instances is running so it actually was able to connect to this instance okay so we locked out there because it's going to start with that and try and connect um so nothing's publishing messages yet so let's open up the management driver mq management and take a look at that okay so in the queues we're looking at this queue so now this queue has got no messages in here right now so it's got zero messages nothing's being worked on no acknowledgements no publishing is going on here and there are messages in the queue but we are listening on the queue so let's do this let's use our other publisher application now this one let me make this thing the active application the startup application okay all right so you could have published this message i mean this thing has already received the message here so when it starts up it publishes one message and we can see he has received the message and now what i'm going to do is each time i hit enter on this console application here we should it should publish a message and we should see that message being received over here there so enter enter enter enter and so on each time i press enter we see the message being received over here and if i keep this enter key pressed on the console application here all the messages are being received over here you go to the gravity mq management you can see lots of acknowledgments taking place here but zero messages are left behind in the queue all right so that's cool so that's working let's make sure when you shut it down it doesn't blow up i mean in case you made some mistakes in the dispose part and then we will make this application a windows service all right okay so let's shut that down no problems there let's shut down uh well publishing you can sit and wait that's our publisher app keep all this running no need to keep stopping and starting these apps all right so now how do we make this a windows service we need to include another nougat called windows services i think so microsoft.extensions.hosting.windows services i think and they need to add that using your users in the console application so let's find the nougat and this one windows sources and once you install that that's that and then in our program cs file here we need to add a using use windows service that's it once you've done that this can now be made into a windows service however you still need to do a few things you have to still install that service in windows this is not going to do it by itself so what we're going to do is we're going to publish this application as a sort of a standalone application with all of the requirements within a certain folder and then we're going to use the command line and we're going to register that application this application with the windows service infrastructure so we can start stop and do all the stuff with it there all right so let's do that so first is you need to publish this application so if you were to publish publish that i didn't pick that up okay we have various options to publish i want to just publish it to a folder on my local machine here and it's going to publish it to i'm going to leave that alone i need to touch it basically he's going to add on the publish folder in addition to this.net 31 which is fine okay we can look at some of the configuration options here uh we're going to do the release build blah framework dependent maybe you should deploy this as a standalone self-contained and maybe since i'm running out win364 like that okay let's do that now we've done that we publish take a few seconds and it's published it okay why isn't it take me to the path all right so let me go back to this publish here what did i do okay not showing me the file path okay so here's the whole project deployed with all of his dependencies in this one folder and that's the executable here now i'm going to use the command line register this application as a windows service started stop it and when we started it is listening for the messages you know publish messages and see now there's no ui i can show you for windows services so we're going to use the trick we're going to use the management rabbit mq management console to see that messages are being consumed when we start the application this service and they're not consumed when we stop it right all right so let's start a command line up and as administrator and i'm going to use the service control modules or service control what they call it service control manager okay let's see let me make the wand a bit bigger here so you guys can see what i'm doing 828 okay wow that's big okay hopefully you can see that so this sc command is the service control manager and using this you can do a bunch of things you can start a service you can pause the service you can stop a service but you need to first create a service and clear service before we can start stop opposite so we're going to first create a service and once we've created our search we can also delete the service once we want to remove it from the windows services registry okay so i don't know what the command line for creators i'm going to say let's see create and enter again that's going to say well in order to create a service you need to provide it the server on which you want to create in this case is local so we'll skip that so sc create the service name this is the name you want to see in your services ui and windows it's not the name of the executable just the name that you would like to use as the service name the path to the executable all right so we do sc create i'm going to call it mq subscriber it's just a name and the bin path is wherever this thing is i'm going to copy this as path and paste it there all right so that's created the service if i went to the services console here and look for private and queue you'll see it here so it's there but it's now started in this manual so i can of course right click here and say start or click to start there or whatever but i'm going to start it from the command line here so we'll say um yeah so instead of create we just say sc start that service and this is what is a start pending yeah so it says start pending but basically it has started it doesn't assume it's it's not a waiver to start so now if i refresh this currently says manual whatever but if i refresh this it just says running and now it's running okay so now this is running let's start publishing messages again using our other application this guy here and we monitor the rav mq console here to make sure one that these messages remain zero and the number of acknowledgements goes up as we publish messages and the service picks it up make sense all right let's try it so back in here i'm happily publishing messages i just got the enter key pressed down here and hopefully in the next five seconds we're gonna see the number of messages remaining zero but the number of acts have gone up see the acknowledgments have gone up but the number of messages in the console are showing at zero right you know this is a refreshing every five seconds so it's not instantaneous but the acknowledgments went up which means we've acknowledged a bunch of messages over 15 16 messages a second almost yeah right so i'm going to start doing it again press the enter key and that's it now let's watch this again the next five seconds again the acknowledgement should go up and the number of messages should still remain zero then it goes up and zero all right now the next step is if you shut down the service if you stop the service and we publish messages the messages should accumulate in it and once you've done that then start the service and the message should disappear okay let's try that so my windows thing here services panel i'm going to stop the service is running currently gonna stop it now there if you get an error when you start or stop those services that you build there's potentially a problem with the way you built that service and so you should never get an error it's not okay to get an error even though it may stop the app or may start the app don't you don't want errors at that point in time okay so we do that and now we publish messages again just kept enter key pressed come back here so now we have 93 messages sitting in the queue for us and no acknowledgments the green in those acknowledgments so there's 14 mesh this is the publish so publishers went up now we have 93 messages in the queue but nobody's been subscribing so therefore the messages are sitting here in the queue now all i'm going to do is just start that service windows service and you can set up these services to start up when the application starts up as you could say something like instrument you can say automatic so automatically means it's going to start automatically when the operating system boots up so each time your machine boots up you can have ourselves running by automatically maybe i don't want to do that here but i can start it so i start that and you'll see now at some point the number of messages here disappears from 93 to zero there gone and so we know our service is working so this is so far the service has been working as a console application or a hosted in a console application remember there's an application that's hosting the hosted service right it's a hosted service all right we're going to take that assembly now when we build the standard dotnet standard assembly take that and use that from a web application and then we're going to contrast some of the differences between a console application and a web application in terms of the hosted services being hosted in a console application or a web application before that i'm going to shut down the service and uninstall it or delete it so let's do that here oh sorry in the console command window here so instead of doing a start i can do a stop here for the service and i must have stopped i can do a delete and that's that if i look at the sources now you know it's there when i refresh it it's gone it's just not no longer registered cool so that's that all right don't need that anymore i'll keep this running still i'll keep that running still actually we don't need it but i'll keep it on anyways and uh don't need that all right now next is to add a hp.net core project to this solution core application and it'll just be well api application let's say so there are two ways to do the registration of a worker service in the asp.net application one is you can go to program cs and do the same thing like we did before so i'm going to open this is the program cs from our previous worker service application and this is the program cs from our let me just open the okay so this one is our vocal service application sorry this was our worker source application that's already registering the rabbit mq and this is the asp.net application just look at the the two sides here you can see they're almost identical the docker light this is something we added recently so but you can see here this says configure web host defaults and this one just says configure services then that's it now we could add like what we did here configure services you can take this you know as it is and do it in there and that'll work kind of like that now we still need that uh well what do you call it the hosted extensions here to be able to do that part here so let's do that it needs to be done in an application i thought it was explicit sorry i thought it was implicit in asp.net but maybe not okay now okay so now that we have that there's something to keep in mind here if you do it in this sequence here you're saying that you want a hosted source to be registered after the pipeline maybe sometimes you want it to be done before the pipeline sometimes you want to do it after the pipeline so the simple way to do that would be just to switch the order of these two right move them up do one before the other kind of thing like that right um like that right but if none of that matters then i would just don't do it in the program cs for your asp.net application just do this registration in the startup so i'm going to take this out of here both ways work either ways work so i'm going to now open up startup and startup we already have a configure services method here so we just do that there right that's that and that's all you need to do in an asp.net application the infrastructure already exists you all need to do is just register your own hosted service signalr is one of those services that runs as a hosted service in an asp.net application so it's something that a lot of the framework already uses and they've just exposed that to us and as i said before it was the usbi web host now it's just ihost so they're independent of anything web related in terms of the infrastructure for the web like from a service standpoint or a server standpoint which used to be the case before not anymore all right so we're taking the same class here that was in the standard dotnet standard library and by the donor standard is disappearing you know that right yeah in dot net five there's no notion of dotnet standard that's it dot net five is it okay so let's run this application and see this background service running so do we have messages in the thing here we don't okay doesn't matter we shall run this application and check it out oh this is the worker service sorry wrong wrong application me create this as the startup application okay and run it so that's the api part of it all right i'm going to publish the messages here and we shall see if they are being act and consumed by our publisher so they've been act you can see went up here and the number of messages in this will be zero right so you know it's working now in hp.net core you have another way to see this because you can run it as a you can run the application rather than you're running it within is express right so you can run the console application where you see the console window and the logger output will be visible to us this and instead of running it in is express let's do that i'm just going to shut this down and here instead of using ios express i can use the the service itself the application and this will show us the console so now you'll see our own console window here and you'll also see they pop the uh events being published here for when we receive messages from our publisher right so there i hit enter it's getting published and sort of being received here subscribed here enter enter keep the enter key pressed and there you go all right so we've gone through the whole thing we just looked at the plain jane worker service we've built our own class that descends from nothing but just implements the i hosted service and the i disposable we've used the background service base class to do our own thing to build avid mq worker service which is a full-fledged implementation we've taken that implementation and use it in a console application and in asp.net application and seen everything working we've also installed that application the console application as a windows service so we pretty much covered all bases here just keep in mind these units of scale aspects of a service even though this is a cool feature it's not normal or always true where your background services have to scale at the same years of scale as your application and maybe sometimes that even causes you trouble so think about those aspects when you're building a background service but if you're just building a background service you don't need it to be in an hp.net application to start with right you just have it as a console application and do it that way all right so that brings us to the end of this video i hope you've enjoyed yourselves i hope you learned a few things if you have please give me a thumbs up and i will see you next time
Info
Channel: Shiv Kumar
Views: 32,556
Rating: undefined out of 5
Keywords: Worker Service, Worker, Background Service, ASP.NET, IHostedService, IHost, IWebHost, C#, .NET, OOD, OOP, Windows Service, Programming With Intent, Background Task, .NET Core
Id: M3qS73D-Vuc
Channel Id: undefined
Length: 61min 21sec (3681 seconds)
Published: Sun Jul 26 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.