{"id":584,"date":"2022-10-20T08:56:52","date_gmt":"2022-10-20T08:56:52","guid":{"rendered":"https:\/\/oussamasaidi.com\/?p=584"},"modified":"2025-12-20T11:15:10","modified_gmt":"2025-12-20T11:15:10","slug":"hangfire-avec-asp-net-core","status":"publish","type":"post","link":"https:\/\/oussamasaidi.com\/en\/hangfire-avec-asp-net-core\/","title":{"rendered":"Hangfire avec ASP.NET Core"},"content":{"rendered":"<p>Presque toutes les applications doivent effectuer une sorte de travail de fond. Qu&rsquo;il s&rsquo;agisse d&rsquo;une t\u00e2che longue et fastidieuse ou d&rsquo;un travail r\u00e9p\u00e9titif que nous devons faire tous les deux jours, dans cet article, nous allons apprendre comment nous pouvons facilement l&rsquo;impl\u00e9menter. Pour cela, nous allons utiliser Hangfire &#8211; une biblioth\u00e8que open source pour ASP.NET Core .<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-style-default is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Pour t\u00e9l\u00e9charger le code source de cet article, vous pouvez visiter notre <a href=\"https:\/\/github.com\/oussama-saidi\/aspcore-hangfire-webapi\" target=\"_blank\" rel=\"noopener\">r\u00e9f\u00e9rentiel Hangfire avec ASP.NET Core<\/a> .<\/p>\n<\/blockquote>\n\n\n<ul><li><a class=\"aioseo-toc-item\" href=\"#introduction\">Introduction aux t\u00e2ches en arri\u00e8re-plan<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#aioseo-quand-devrions-nous-utiliser-le-traitement-en-arriere-plan\">Quand devrions-nous utiliser le traitement en arri\u00e8re-plan\u00a0?<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#what-is-hangfire\">Qu&#039;est-ce que Hangfire\u00a0?<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#aioseo-caracteristiques-les-plus-remarquables-de-hangfire\">Caract\u00e9ristiques les plus remarquables de Hangfire<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#how-hangfire-works\">Comment fonctionne Hangfire\u00a0?<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#aioseo-le-role-de-chaque-composant\">Le r\u00f4le de chaque composant<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#aioseo-le-flux-de-travail-hangfire\">Le flux de travail Hangfire<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#setting-up\">Configuration de Hangfire dans ASP.NET Core<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#aioseo-paquet-hangfire-nuget\">Paquet Hangfire NuGet<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#aioseo-stockage-persistant\">Stockage persistant<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#aioseo-classe-de-demarrage\">Classe de d\u00e9marrage<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#dashboard\">Tableau de bord Hangfire<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#job-types\">Types d&#039;emplois en arri\u00e8re-plan dans Hangfire<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#aioseo-emplois-fire-and-forget\">Emplois Fire and Forget<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#aioseo-taches-retardees\">T\u00e2ches retard\u00e9es<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#aioseo-emplois-recurrents\">Emplois r\u00e9currents<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#aioseo-emplois-de-continuation\">Emplois de continuation<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#conclusion\">Conclusion<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#aioseo-dernier-articles\">Dernier articles<\/a><\/li><\/ul>\n\n\n<h2 class=\"wp-block-heading\" id=\"introduction\">Introduction aux t\u00e2ches en arri\u00e8re-plan<\/h2>\n\n\n\n<p>Pour assurer le bon fonctionnement de nos applications et la satisfaction de nos utilisateurs, nous pouvons utiliser pour certaines t\u00e2ches un concept appel\u00e9 traitement en arri\u00e8re-plan. Une t\u00e2che est une m\u00e9thode dans notre code avec une logique que nous devons ex\u00e9cuter. Le traiter en arri\u00e8re-plan signifie que nous pouvons l&rsquo;ex\u00e9cuter en dehors du thread principal de l&rsquo;application.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-quand-devrions-nous-utiliser-le-traitement-en-arriere-plan\">Quand devrions-nous utiliser le traitement en arri\u00e8re-plan&nbsp;?<\/h3>\n\n\n\n<p>Il existe de nombreuses situations dans lesquelles nous devons garder un travail sp\u00e9cifique loin des projecteurs.<\/p>\n\n\n\n<p>Parfois, il s&rsquo;agit d&rsquo;une t\u00e2che de longue haleine dont l&rsquo;affichage des donn\u00e9es de l&rsquo;interface utilisateur ne d\u00e9pend pas et qui ralentit le flux de l&rsquo;application. Un exemple pourrait \u00eatre de t\u00e9l\u00e9charger un tas de photos sur une plate-forme de m\u00e9dias sociaux. Nous ne voudrions pas que cette action emp\u00eache nos utilisateurs d&rsquo;utiliser la plateforme pendant que nous traitons les photos. Nous pouvons effectuer la t\u00e2che de t\u00e9l\u00e9chargement dans les coulisses et l&rsquo;utilisateur peut continuer \u00e0 naviguer librement.<\/p>\n\n\n\n<p>Nous pouvons \u00e9galement avoir besoin de planifier certaines t\u00e2ches pour qu&rsquo;elles s&rsquo;ex\u00e9cutent toutes les heures, toutes les semaines ou peut-\u00eatre tous les mois. Comme surveiller les utilisateurs inactifs ou envoyer des factures d&rsquo;abonnement. Ou nous devrons peut-\u00eatre envoyer une notification \u00e0 notre utilisateur une fois, sauf pas maintenant, mais dans environ trois jours.<\/p>\n\n\n\n<p>Nous pouvons g\u00e9rer toutes ces t\u00e2ches avec un bon planificateur de t\u00e2ches en arri\u00e8re-plan qui s&rsquo;occupe des d\u00e9tails pour nous. C&rsquo;est l\u00e0 que Hangfire brille.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-is-hangfire\">Qu&rsquo;est-ce que Hangfire&nbsp;?<\/h2>\n\n\n\n<p>Hangfire est un planificateur de t\u00e2ches open source et bien document\u00e9 pour ASP.NET et ASP.NET Core. Il est multithread, facilement \u00e9volutif et offre une vari\u00e9t\u00e9 de types de travaux. Il est bien structur\u00e9, simple \u00e0 utiliser et offre des performances puissantes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-caracteristiques-les-plus-remarquables-de-hangfire\">Caract\u00e9ristiques les plus remarquables de Hangfire<\/h3>\n\n\n\n<p>Compar\u00e9 aux autres planificateurs disponibles, Hangfire offre de nombreux avantages. Entre autres choses, il est particuli\u00e8rement facile \u00e0 installer et \u00e0 configurer, il utilise un stockage persistant et il dispose d&rsquo;un joli tableau de bord d&rsquo;interface utilisateur pour v\u00e9rifier nos travaux \u00e0 tout moment. Il prend en charge le traitement de plusieurs files d&rsquo;attente et nous pouvons \u00e9galement choisir explicitement la file d&rsquo;attente que nous voulons utiliser pour un travail sp\u00e9cifique.<\/p>\n\n\n\n<p>Parce que le stockage persistant enregistre l&rsquo;\u00e9tat du travail, nous avons \u00e9galement un grand bonus &#8211; les tentatives de travail. Cette fonctionnalit\u00e9 permet de s&rsquo;assurer que nos travaux finissent de s&rsquo;ex\u00e9cuter m\u00eame s&rsquo;ils rencontrent une exception transitoire ou si le pool d&rsquo;applications d\u00e9di\u00e9e tombe en panne. Si une t\u00e2che \u00e9choue, Hangfire essaiera de l&rsquo;ex\u00e9cuter \u00e0 nouveau d\u00e8s que possible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-hangfire-works\">Comment fonctionne Hangfire&nbsp;?<\/h2>\n\n\n\n<p>L&rsquo;architecture Hangfire comporte trois composants principaux&nbsp;: le client, le serveur et le stockage. Ils sont \u00e9troitement li\u00e9s dans l&rsquo;ensemble du processus et d\u00e9pendent les uns des autres.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-le-role-de-chaque-composant\">Le r\u00f4le de chaque composant<\/h3>\n\n\n\n<p>Voyons ce dont chaque composant est responsable&nbsp;:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Client Hangfire<\/strong> &#8211; Ce sont les biblioth\u00e8ques r\u00e9elles de notre application. Le client cr\u00e9e le travail, s\u00e9rialise sa d\u00e9finition et s&rsquo;assure de le stocker dans notre stockage persistant.<\/li>\n\n\n\n<li><strong>Stockage Hangfire<\/strong> &#8211; Ceci est notre base de donn\u00e9es. Il utilise quelques tables d\u00e9sign\u00e9es que Hangfire cr\u00e9e pour nous. Il stocke toutes les informations sur nos t\u00e2ches &#8211; d\u00e9finitions, statut d&rsquo;ex\u00e9cution, etc. Hangfire prend en charge les options RDBMS et NoSQL, nous pouvons donc choisir celle qui convient \u00e0 notre projet. Par d\u00e9faut, il utilise SQL Server, mais toute autre option prise en charge est \u00e9galement facile \u00e0 configurer.<\/li>\n\n\n\n<li><strong>Serveur Hangfire<\/strong> &#8211; Le serveur a pour t\u00e2che de r\u00e9cup\u00e9rer les d\u00e9finitions de travail du stockage et de les ex\u00e9cuter. Il est \u00e9galement responsable de garder notre stockage de travail propre de toutes les donn\u00e9es que nous n&rsquo;utilisons plus. Le serveur peut vivre dans notre application ou sur un autre serveur. Il pointe toujours vers le stockage de la base de donn\u00e9es donc son emplacement ne joue pas de r\u00f4le, mais cette diversit\u00e9 peut \u00eatre tr\u00e8s utile.<\/li>\n<\/ul>\n\n\n\n<p>\u00c9tant donn\u00e9 que Hangfire est con\u00e7u de mani\u00e8re aussi g\u00e9n\u00e9rique que possible, nous pouvons \u00e9galement \u00e9tendre manuellement certaines de ses parties telles que la mise en \u0153uvre du stockage, la cr\u00e9ation de t\u00e2ches ou les processus d&rsquo;activation de t\u00e2ches pour r\u00e9pondre \u00e0 des besoins sp\u00e9cifiques.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-le-flux-de-travail-hangfire\">Le flux de travail Hangfire<\/h3>\n\n\n\n<p>Le flux de travail entre les composants est assez simple&nbsp;:<\/p>\n\n\n\n<p>Une fois que nous avons sp\u00e9cifi\u00e9 notre t\u00e2che dans le code et appel\u00e9 la m\u00e9thode Hangfire appropri\u00e9e pour la cr\u00e9er, le client Hangfire cr\u00e9e la t\u00e2che et la stocke dans la base de donn\u00e9es. Le contr\u00f4le revient ensuite \u00e0 l&rsquo;application afin que le thread principal puisse poursuivre son travail.<br>Lorsqu&rsquo;un travail se trouve dans le stockage, le serveur le r\u00e9cup\u00e8re et cr\u00e9e un thread d&rsquo;arri\u00e8re-plan pour traiter le travail r\u00e9cup\u00e9r\u00e9.<\/p>\n\n\n\n<p>On peut repr\u00e9senter ce flux avec quatre actions cons\u00e9cutives dans deux branches diff\u00e9rentes \u2013 une entre client et stockage et l&rsquo;autre entre stockage et serveur :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img fetchpriority=\"high\" decoding=\"async\" width=\"881\" height=\"601\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-588\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image.png 881w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-300x205.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-768x524.png 768w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-18x12.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-256x175.png 256w\" sizes=\"(max-width: 881px) 100vw, 881px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setting-up\">Configuration de Hangfire dans ASP.NET Core<\/h2>\n\n\n\n<p>Apr\u00e8s avoir appris les m\u00e9canismes de l&rsquo;architecture Hangfire, voyons comment cela fonctionne dans la pratique.<\/p>\n\n\n\n<p>Pour commencer, cr\u00e9ons un nouveau projet d&rsquo;API Web ASP.NET Core&nbsp;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"870\" height=\"581\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-1.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-589\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-1.png 870w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-1-300x200.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-1-768x513.png 768w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-1-18x12.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-1-256x171.png 256w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/figure>\n\n\n\n<p>Nous utiliserons \u00e9galement Swagger pour envoyer des requ\u00eates HTTP. Nous pouvons facilement l&rsquo;ajouter \u00e0 notre .NET 5.0. projet si nous cochons la case Activer le support OpenAPI&nbsp;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"834\" height=\"558\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-2.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-590\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-2.png 834w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-2-300x201.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-2-768x514.png 768w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-2-18x12.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-2-256x171.png 256w\" sizes=\"(max-width: 834px) 100vw, 834px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-paquet-hangfire-nuget\">Paquet Hangfire NuGet<\/h3>\n\n\n\n<p>Tout d&rsquo;abord, nous allons installer le package Hangfire NuGet. Nous pouvons rechercher Hangfire dans le gestionnaire de paquets&nbsp;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"723\" height=\"87\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-3.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-591\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-3.png 723w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-3-300x36.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-3-18x2.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-3-256x31.png 256w\" sizes=\"(max-width: 723px) 100vw, 723px\" \/><\/figure>\n\n\n\n<p>ou ex\u00e9cutez la commande dans la console du gestionnaire de packages&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"false\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">PM> Install-Package Hangfire<\/pre>\n\n\n\n<p>Apr\u00e8s avoir install\u00e9 ce package, il r\u00e9f\u00e9rence par d\u00e9faut d&rsquo;autres packages n\u00e9cessaires tels que Hangfire.Core et Hangfire.SqlServer et vous n&rsquo;avez pas \u00e0 vous en soucier.<br>L&rsquo;exception est si vous utilisez une option de stockage diff\u00e9rente de SQL Server. Dans ce cas, assurez-vous d&rsquo;ajouter le package NuGet suppl\u00e9mentaire pour ce type de stockage.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-stockage-persistant\">Stockage persistant<\/h3>\n\n\n\n<p>Pour stocker les d\u00e9finitions et les statuts des t\u00e2ches, comme nous l&rsquo;avons maintenant appris, Hangfire peut utiliser une base de donn\u00e9es SQL Server par d\u00e9faut et nous pouvons \u00e9galement choisir d&rsquo;autres options. Dans notre exemple de projet, par souci de simplicit\u00e9, nous allons utiliser le stockage MSSQL LocalDB.<\/p>\n\n\n\n<p>Quel que soit le type de base de donn\u00e9es que nous utilisons, locale ou distante, nous devrions avoir une d\u00e9finition de base de donn\u00e9es &#8211; m\u00eame si elle est vide. Hangfire cr\u00e9era les tables dont nous avons besoin pour le stockage des t\u00e2ches, mais il ne peut pas cr\u00e9er de base de donn\u00e9es, nous devons donc la fournir.<\/p>\n\n\n\n<p>Apr\u00e8s avoir configur\u00e9 notre base de donn\u00e9es locale, nous devons mettre \u00e0 jour le fichier <em>appsettings.json<\/em>&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\"AllowedHosts\": \"*\",\n    \"ConnectionStrings\": {\n        \"DBConnection\": \"Server=(localdb)\\\\MSSQLLocalDB;Database=HangfireApplication;Trusted_Connection=True\"\n    }<\/pre>\n\n\n\n<p>Dans l&rsquo;objet ConnectionStrings, nous ajoutons notre cha\u00eene de connexion LocalDB. Si vous avez d\u00e9cid\u00e9 d&rsquo;utiliser une base de donn\u00e9es d\u00e9j\u00e0 existante ou simplement une alternative \u00e0 LocalDB, vous devez modifier la cha\u00eene de connexion pour votre cas sp\u00e9cifique.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-classe-de-demarrage\">Classe de d\u00e9marrage<\/h3>\n\n\n\n<p>Apr\u00e8s avoir install\u00e9 le package Hangfire et configur\u00e9 la base de donn\u00e9es, nous devons \u00e9galement configurer notre classe <em>Startup<\/em>&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public void ConfigureServices(IServiceCollection services)\n{\n    services.AddControllers();\n    services.AddSwaggerGen(c =>\n    {\n        c.SwaggerDoc(\"v1\", new OpenApiInfo { Title = \"HangfireApplication\", Version = \"v1\" });\n    });\n    services.AddHangfire(x =>\n    {\n        x.UseSqlServerStorage(Configuration.GetConnectionString(\"DBConnection\"));\n    });\n    services.AddHangfireServer();\n}<\/pre>\n\n\n\n<p>Dans la <code>ConfigureServices<\/code>m\u00e9thode, avec la <code>AddHangfire()<\/code>m\u00e9thode, nous ajoutons le service Hangfire avec l&rsquo;option de stockage SQL Server. Nous fournissons la cha\u00eene de connexion que nous avons sp\u00e9cifi\u00e9e dans le fichier appsettings.json.<br>Nous ajoutons \u00e9galement le serveur Hangfire avec la <code>AddHangfireServer()<\/code>m\u00e9thode. Le serveur Hangfire de notre projet va vivre \u00e0 l&rsquo;int\u00e9rieur de l&rsquo;application.<\/p>\n\n\n\n<p>De plus, nous devons mettre \u00e0 jour notre pipeline de traitement des demandes&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n{\n    if (env.IsDevelopment())\n    {\n        app.UseDeveloperExceptionPage();\n        app.UseSwagger();\n        app.UseSwaggerUI(c => c.SwaggerEndpoint(\"\/swagger\/v1\/swagger.json\", \"HangfireApplication v1\"));\n    }\n    app.UseHttpsRedirection();\n    app.UseRouting();\n    app.UseAuthorization();\n    app.UseEndpoints(endpoints =>\n    {\n        endpoints.MapControllers();\n    });\n    app.UseHangfireDashboard();\n}<\/pre>\n\n\n\n<p>Dans la <code>Configure<\/code>m\u00e9thode, nous ajoutons le tableau de bord Hangfire \u00e0 notre pipeline, en appelant la <code>UseHangfireDashboard()<\/code>m\u00e9thode, afin que nous puissions facilement surveiller nos travaux ult\u00e9rieurement.<\/p>\n\n\n\n<p>Ce tableau de bord est, par d\u00e9faut, configur\u00e9 pour \u00eatre accessible uniquement localement, mais si vous souhaitez y acc\u00e9der \u00e0 distance, vous pouvez \u00e9galement le configurer. Cependant, il expose de nombreuses informations sensibles, soyez donc toujours prudent avec cette configuration.<\/p>\n\n\n\n<p>Lorsque nous ex\u00e9cutons notre application, Hangfire v\u00e9rifiera automatiquement notre stockage d\u00e9sign\u00e9 pour les tables n\u00e9cessaires, et si elles n&rsquo;existent pas encore, il les cr\u00e9era pour nous&nbsp;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"380\" height=\"398\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-4.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-594\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-4.png 380w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-4-286x300.png 286w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-4-11x12.png 11w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-4-244x256.png 244w\" sizes=\"(max-width: 380px) 100vw, 380px\" \/><\/figure>\n\n\n\n<p>C&rsquo;est tout en ce qui concerne la configuration et nous sommes tous pr\u00eats \u00e0 commencer \u00e0 utiliser Hangfire. Inspectons maintenant rapidement le tableau de bord Hangfire, puis voyons comment cr\u00e9er des t\u00e2ches en arri\u00e8re-plan.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"dashboard\">Tableau de bord Hangfire<\/h2>\n\n\n\n<p>Si nous d\u00e9marrons notre application et naviguons vers l&rsquo;URL <em>https:\/\/localhost:5001\/hangfire<\/em> , nous pouvons voir le tableau de bord tr\u00e8s utile inclus :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"890\" height=\"536\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-5.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-595\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-5.png 890w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-5-300x181.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-5-768x463.png 768w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-5-18x12.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-5-256x154.png 256w\" sizes=\"(max-width: 890px) 100vw, 890px\" \/><\/figure>\n\n\n\n<p>Dans le tableau de bord, nous pouvons voir toutes les t\u00e2ches en cours et planifi\u00e9es que nous cr\u00e9ons avec notre client Hangfire. Nous pouvons \u00e9galement surveiller les serveurs, les tentatives de travail, les travaux \u00e9chou\u00e9s et garder un \u0153il sur tous les travaux dans la file d&rsquo;attente. Une autre grande chose que nous pouvons faire dans le tableau de bord est que nous pouvons d\u00e9clencher manuellement toutes les t\u00e2ches existantes.<\/p>\n\n\n\n<p>Nous couvrirons les autres onglets un peu plus tard lorsque nous essaierons les diff\u00e9rents types de travaux pris en charge par Hangfire, mais pour l&rsquo;instant, v\u00e9rifions rapidement l&rsquo; onglet <em>Serveurs&nbsp;:<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"890\" height=\"249\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-6.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-596\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-6.png 890w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-6-300x84.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-6-768x215.png 768w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-6-18x5.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-6-256x72.png 256w\" sizes=\"(max-width: 890px) 100vw, 890px\" \/><\/figure>\n\n\n\n<p>Ici, nous pouvons voir le serveur qui s&rsquo;ex\u00e9cute dans notre application de test. Si nous avions plus d&rsquo;instances de serveur en cours d&rsquo;ex\u00e9cution, nous les verrions \u00e9galement r\u00e9pertori\u00e9es ici. Hangfire v\u00e9rifie p\u00e9riodiquement l&rsquo;utilisation du serveur, donc s&rsquo;il y a un serveur qui n&rsquo;est plus utilis\u00e9, il sera automatiquement supprim\u00e9 de la liste.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"job-types\">Types d&#8217;emplois en arri\u00e8re-plan dans Hangfire<\/h2>\n\n\n\n<p>Hangfire prend en charge diff\u00e9rents types de t\u00e2ches que nous pouvons utiliser pour diff\u00e9rentes occasions. Des t\u00e2ches ponctuelles aux t\u00e2ches quotidiennes, nous sommes couverts. Voyons comment les mettre en \u0153uvre facilement et v\u00e9rifier leur ex\u00e9cution dans le tableau de bord.<\/p>\n\n\n\n<p>Pour commencer \u00e0 tester la planification des t\u00e2ches, cr\u00e9ons un dossier <em>Services avec une classe JobTestService<\/em> et son interface d&rsquo;appartenance&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public interface IJobTestService\n{\n    void FireAndForgetJob();\n    void ReccuringJob();\n    void DelayedJob();\n    void ContinuationJob();\n}<\/pre>\n\n\n\n<p>Tout d&rsquo;abord, nous sp\u00e9cifions l&rsquo; interface <em>IJobTestService<\/em> o\u00f9 nous enregistrons quatre m\u00e9thodes diff\u00e9rentes &#8211; nomm\u00e9es de mani\u00e8re pratique d&rsquo;apr\u00e8s les types de travaux Hangfire.<\/p>\n\n\n\n<p>Apr\u00e8s cela, nous pouvons passer \u00e0 la modification de la classe de service&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public class JobTestService : IJobTestService\n{\n    public void FireAndForgetJob()\n    {\n        Console.WriteLine(\"Hello from a Fire and Forget job!\");\n    }\n    public void ReccuringJob()\n    {\n        Console.WriteLine(\"Hello from a Scheduled job!\");\n    }\n    public void DelayedJob()\n    {\n        Console.WriteLine(\"Hello from a Delayed job!\");\n    }\n    public void ContinuationJob()\n    {\n        Console.WriteLine(\"Hello from a Continuation job!\");\n    }\n}<\/pre>\n\n\n\n<p>Notre classe <em>JobTestService<\/em> impl\u00e9mente l&rsquo; interface <em>IJobTestService<\/em> que nous avons cr\u00e9\u00e9e. Chaque m\u00e9thode de la classe n&rsquo;imprime que du texte sur notre console, au lieu de faire le travail r\u00e9el comme elle le ferait dans une application r\u00e9elle.<\/p>\n\n\n\n<p>Dans le monde r\u00e9el, \u00e0 l&rsquo;int\u00e9rieur de m\u00e9thodes comme celles-ci, il peut y avoir un code qui t\u00e9l\u00e9charge une photo ou v\u00e9rifie l&rsquo;inactivit\u00e9 de l&rsquo;utilisateur. Dans notre exemple, les appels simples <code>Console.WriteLine()<\/code>nous permettront de nous concentrer davantage sur la planification des travaux.<\/p>\n\n\n\n<p>Apr\u00e8s avoir d\u00e9fini la classe de service, nous devons \u00e0 nouveau modifier notre classe <em>Startup<\/em>&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public void ConfigureServices(IServiceCollection services)\n{\n    services.AddControllers();\n    services.AddSwaggerGen(c =>\n    {\n        c.SwaggerDoc(\"v1\", new OpenApiInfo { Title = \"HangfireApplication\", Version = \"v1\" });\n    });\n            \n    services.AddScoped&lt;IJobTestService, JobTestService>();\n    services.AddHangfire(x =>\n    {\n        x.UseSqlServerStorage(Configuration.GetConnectionString(\"DBConnection\"));\n    });\n    services.AddHangfireServer();\n}<\/pre>\n\n\n\n<p>Pour pouvoir utiliser notre nouveau service avec injection de d\u00e9pendances, \u00e0 l&rsquo;int\u00e9rieur de la <code>ConfigureServices()<\/code>m\u00e9thode, nous enregistrons notre impl\u00e9mentation d&rsquo;interface \u00e0 l&rsquo;aide de la <code>AddScoped()<\/code>m\u00e9thode.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-emplois-fire-and-forget\">Emplois Fire and Forget<\/h3>\n\n\n\n<p>Le premier type de travail que nous allons couvrir est le travail Fire and Forget. Lorsque nous cr\u00e9ons ce type de job, le serveur ne l&rsquo;ex\u00e9cute qu&rsquo;une seule fois, d\u00e8s qu&rsquo;il le peut.<\/p>\n\n\n\n<p>Dans le dossier <em>Controllers<\/em> de notre application, nous pouvons cr\u00e9er et modifier un fichier <em>JobTestController.cs<\/em>&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[Route(\"api\/[controller]\")]\n[ApiController]\npublic class JobTestController : ControllerBase\n{\n    private readonly IJobTestService _jobTestService;\n    private readonly IBackgroundJobClient _backgroundJobClient;\n    public JobTestController(IJobTestService jobTestService, IBackgroundJobClient backgroundJobClient)\n    {\n        _jobTestService = jobTestService;\n        _backgroundJobClient = backgroundJobClient;\n    }<\/pre>\n\n\n\n<p>Nous cr\u00e9ons le constructeur JobTestController et injectons l&rsquo; interface <em>IBackgroundJobClient<\/em> fournie par Hangfire. Nous utiliserons les m\u00e9thodes de cette interface pour planifier diff\u00e9rents types de t\u00e2ches. En plus de cela, nous injectons \u00e9galement l&rsquo; interface <em>IJobTestService<\/em> que nous avons cr\u00e9\u00e9e.<\/p>\n\n\n\n<p>Ajoutons maintenant un point de terminaison de test qui nous aidera \u00e0 planifier la t\u00e2che&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[HttpGet(\"\/FireAndForgetJob\")]\npublic ActionResult CreateFireAndForgetJob()\n{\n    _backgroundJobClient.Enqueue(() => _jobTestService.FireAndForgetJob());\n    return Ok();\n}<\/pre>\n\n\n\n<p>Notre nouveau point de terminaison utilise l&rsquo;interface Hangfire inject\u00e9e pour planifier ce type de t\u00e2che. Nous appelons la m\u00e9thode de l&rsquo;interface <code>Enqueue()<\/code>et lui transmettons notre <code>FireAndForgetJob()<\/code>appel de m\u00e9thode de service en tant que param\u00e8tre.<br>Cette m\u00e9thode pratique de mise en file d&rsquo; <em>attente<\/em> prend soin de cr\u00e9er et d&rsquo;enregistrer la d\u00e9finition de t\u00e2che dans notre stockage et, bien s\u00fbr, de la mettre en file d&rsquo;attente pour le traitement.<\/p>\n\n\n\n<p>Maintenant, nous pouvons envoyer une requ\u00eate GET \u00e0 ce point de terminaison en utilisant Swagger, et par cons\u00e9quent, cela va cr\u00e9er notre premier travail avec Hangfire&nbsp;!<\/p>\n\n\n\n<p>Apr\u00e8s avoir envoy\u00e9 la demande, v\u00e9rifions le travail dans le tableau de bord. Acc\u00e9dez \u00e0 l&rsquo; onglet <em>Jobs , o\u00f9 il devrait maintenant \u00eatre visible sous la section Succeeded<\/em>&nbsp;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"895\" height=\"357\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-7.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-597\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-7.png 895w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-7-300x120.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-7-768x306.png 768w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-7-18x7.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-7-256x102.png 256w\" sizes=\"(max-width: 895px) 100vw, 895px\" \/><\/figure>\n\n\n\n<p>Ici, nous pouvons r\u00e9ex\u00e9cuter manuellement n&rsquo;importe quel travail r\u00e9ussi si nous le souhaitons, avec le bouton <em>Remettre en file d&rsquo;attente les<\/em> <em>travaux<\/em> .<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-taches-retardees\">T\u00e2ches retard\u00e9es<\/h3>\n\n\n\n<p>Les t\u00e2ches retard\u00e9es sont celles que nous voulons s\u00fbrement ex\u00e9cuter, mais pas tout de suite. Nous pouvons les programmer \u00e0 une certaine heure, peut-\u00eatre dans une minute ou dans trois mois.<\/p>\n\n\n\n<p>Pour tester ce type de job, cr\u00e9ons un nouveau endpoint dans notre <em>JobTestController<\/em> :<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[HttpGet(\"\/DelayedJob\")]\npublic ActionResult CreateDelayedJob()\n{\n    _backgroundJobClient.Schedule(() => _jobTestService.DelayedJob(), TimeSpan.FromSeconds(60));\n    return Ok();\n}<\/pre>\n\n\n\n<p>Nous ajoutons un point de <code>CreateDelayedJob()<\/code>terminaison, o\u00f9 nous utilisons \u00e0 nouveau l&rsquo; interface <em>IBackgroundJobClient<\/em> . Cette fois, cependant, nous n&rsquo;appelons pas la <code>Enqueue()<\/code>m\u00e9thode. Au lieu de cela, nous utilisons la <code>Schedule()<\/code>m\u00e9thode et nous lui passons deux param\u00e8tres &#8211; notre <code>DelayedJob()<\/code>appel de m\u00e9thode de service et le d\u00e9lai.<\/p>\n\n\n\n<p>La <code>Schedule()<\/code>m\u00e9thode cr\u00e9era la d\u00e9finition de la t\u00e2che et l&rsquo;enregistrera, mais elle s&rsquo;assurera \u00e9galement de la planifier dans la file d&rsquo;attente \u00e0 l&rsquo;heure sp\u00e9cifi\u00e9e.<\/p>\n\n\n\n<p>D\u00e9sormais, lorsque nous envoyons une requ\u00eate GET \u00e0 ce point de terminaison, nous planifions une t\u00e2che 60&nbsp;secondes dans le futur. Il s&rsquo;affiche dans la section <em>Planifi\u00e9e<\/em> de l&rsquo; onglet <em>T\u00e2ches du tableau de bord&nbsp;:<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"895\" height=\"288\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-8.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-598\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-8.png 895w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-8-300x97.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-8-768x247.png 768w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-8-18x6.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-8-256x82.png 256w\" sizes=\"(max-width: 895px) 100vw, 895px\" \/><\/figure>\n\n\n\n<p>Une fois ex\u00e9cut\u00e9 avec succ\u00e8s, il passe \u00e0 l&rsquo; onglet <em>R\u00e9ussi .<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-emplois-recurrents\">Emplois r\u00e9currents<\/h3>\n\n\n\n<p>Nous planifions nos t\u00e2ches r\u00e9currentes afin qu&rsquo;elles puissent se r\u00e9p\u00e9ter \u00e0 un certain intervalle. Pour ces types de t\u00e2ches, Hangfire utilise l&rsquo;utilitaire logiciel CRON.<\/p>\n\n\n\n<p>Pour planifier ce travail, nous aurons besoin d&rsquo;une interface Hangfire diff\u00e9rente, alors modifions d&rsquo;abord le constructeur de notre contr\u00f4leur&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[Route(\"api\/[controller]\")]\n[ApiController]\npublic class JobTestController : ControllerBase\n{\n    private readonly IJobTestService _jobTestService;\n    private readonly IBackgroundJobClient _backgroundJobClient;\n    private readonly IRecurringJobManager _recurringJobManager;\n    public JobTestController(IJobTestService jobTestService, IBackgroundJobClient backgroundJobClient, IRecurringJobManager recurringJobManager)\n    {\n        _jobTestService = jobTestService;\n        _backgroundJobClient = backgroundJobClient;\n        _recurringJobManager = recurringJobManager;\n    }<\/pre>\n\n\n\n<p>Nous injectons maintenant \u00e9galement l&rsquo;interface Hangfire <em>IReccuringJobManager<\/em> dans le constructeur. Il expose des m\u00e9thodes utiles pour g\u00e9rer les t\u00e2ches r\u00e9currentes et nous l&rsquo;utiliserons pour planifier notre nouvelle t\u00e2che.<\/p>\n\n\n\n<p>Nous pouvons maintenant cr\u00e9er un nouveau point de terminaison pour tester la t\u00e2che&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[HttpGet(\"\/ReccuringJob\")]\npublic ActionResult CreateReccuringJob()\n{\n    _recurringJobManager.AddOrUpdate(\"jobId\", () => _jobTestService.ReccuringJob(), Cron.Minutely);\n    return Ok();\n}<\/pre>\n\n\n\n<p>Nous utilisons la m\u00e9thode de l&rsquo;interface nouvellement inject\u00e9e <code>AddOrUpdate()<\/code>. \u00c0 cette m\u00e9thode, nous transmettons un identifiant de travail de choix, notre <code>RecurringJob()<\/code>appel de m\u00e9thode et l&rsquo;intervalle CRON.<br>La m\u00e9thode hangfire cr\u00e9era une nouvelle t\u00e2che avec l&rsquo;identifiant sp\u00e9cifi\u00e9 ou mettra \u00e0 jour une t\u00e2che existante. Dans cet exemple, nous allons simplement cr\u00e9er le travail pour la premi\u00e8re fois.<\/p>\n\n\n\n<p>Apr\u00e8s avoir envoy\u00e9 une requ\u00eate GET au point de terminaison \u00e0 l&rsquo;aide de Swagger, notre travail r\u00e9current devient visible sous l&rsquo; onglet <em>Travaux r\u00e9currents du tableau de bord&nbsp;:<\/em> <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"895\" height=\"354\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-9.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-599\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-9.png 895w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-9-300x119.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-9-768x304.png 768w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-9-18x7.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-9-256x101.png 256w\" sizes=\"(max-width: 895px) 100vw, 895px\" \/><\/figure>\n\n\n\n<p>Bien que cela montre que nous avons programm\u00e9 notre travail pour qu&rsquo;il se r\u00e9p\u00e8te \u00e0 l&rsquo;heure sp\u00e9cifi\u00e9e, chaque fois que le serveur le traite, l&rsquo;instance trait\u00e9e devient visible dans la section R\u00e9ussite de l&rsquo; onglet <em>Travaux .<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aioseo-emplois-de-continuation\">Emplois de continuation<\/h3>\n\n\n\n<p>Le dernier type de travail que nous allons couvrir est le travail de continuation. Sa principale caract\u00e9ristique est d&rsquo;encha\u00eener l&rsquo;ex\u00e9cution des t\u00e2ches. Avec lui, nous pouvons faire en sorte que deux t\u00e2ches s&rsquo;ex\u00e9cutent l&rsquo;une apr\u00e8s l&rsquo;autre en continu.<\/p>\n\n\n\n<p>Nous avons d\u00e9j\u00e0 une m\u00e9thode pour ce type de travail pr\u00e9par\u00e9e dans notre classe de service, modifions donc notre contr\u00f4leur&nbsp;:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[HttpGet(\"\/ContinuationJob\")]\npublic ActionResult CreateContinuationJob()\n{\n    var parentJobId = _backgroundJobClient.Enqueue(() => _jobTestService.FireAndForgetJob());\n    _backgroundJobClient.ContinueJobWith(parentJobId, () => _jobTestService.ContinuationJob());\n            \n    return Ok();\n}<\/pre>\n\n\n\n<p>Dans le point de <code>CreateContinuationJob()<\/code>terminaison, nous utilisons \u00e0 nouveau l&rsquo;interface Hangfire <em>IBackgroundJobClient<\/em> . Nous l&rsquo;utilisons d&rsquo;abord pour cr\u00e9er un simple travail Fire and Forget &#8211; maintenant nous savons comment faire cela :).<br>Nous voulons que cette t\u00e2che soit un d\u00e9clencheur pour la t\u00e2che suivante, nous nous assurons donc de collecter l&rsquo;identifiant <code>Enqueue()<\/code>renvoy\u00e9 par la m\u00e9thode. Apr\u00e8s sa cr\u00e9ation, nous appelons la m\u00e9thode de l&rsquo;interface <code>ContinueJobWith()<\/code>et transmettons l&rsquo;ID de travail du travail cr\u00e9\u00e9 avec notre <code>ContinuationJob()<\/code>appel de m\u00e9thode. La <code>ContinueJobWith()<\/code>m\u00e9thode fera en sorte d&rsquo;encha\u00eener nos deux jobs ensemble.<\/p>\n\n\n\n<p>Apr\u00e8s avoir atteint ce point de terminaison avec une requ\u00eate GET, si nous v\u00e9rifions la section Succeeded de l&rsquo; onglet <em>Jobs<\/em> du Dashboard, nous pouvons voir que nos deux jobs se sont ex\u00e9cut\u00e9s l&rsquo;un apr\u00e8s l&rsquo;autre&nbsp;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"895\" height=\"413\" src=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-10.png\" alt=\"Hangfire avec ASP.NET Core\" class=\"wp-image-601\" srcset=\"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-10.png 895w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-10-300x138.png 300w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-10-768x354.png 768w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-10-18x8.png 18w, https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/image-10-256x118.png 256w\" sizes=\"(max-width: 895px) 100vw, 895px\" \/><\/figure>\n\n\n\n<p>Super, tout fonctionne !<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>Nous avons beaucoup appris sur la biblioth\u00e8que simple et puissante appel\u00e9e Hangfire. Nous savons maintenant comment le configurer dans notre application ASP.NET Core et comment l&rsquo;utiliser pour planifier diff\u00e9rents types de t\u00e2ches. Il est maintenant temps d&rsquo;aller planifier des t\u00e2ches en arri\u00e8re-plan&nbsp;!<\/p>\n\n\n\n<p>Jusqu&rsquo;au prochain article.<\/p>\n\n\n\n<p>Meilleures salutations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"aioseo-dernier-articles\">Dernier articles<\/h2>\n\n\n\n<ul class=\"wp-block-list\" id=\"block-0b84e8a3-6f95-4f2b-8301-96412ab69281\">\n<li><a href=\"https:\/\/oussamasaidi.com\/en\/hangfire-avec-asp-net-core\/\" target=\"_blank\" rel=\"noopener nofollow sponsored ugc\" title=\"\">Hangfire avec ASP.NET Core<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/oussamasaidi.com\/en\/automapper-net-core\/\" target=\"_blank\" rel=\"noopener nofollow sponsored ugc\" title=\"\">Premiers pas avec AutoMapper dans ASP.NET Core<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/oussamasaidi.com\/en\/serilog-in-aspnet-core-3-1\/\" target=\"_blank\" rel=\"noopener nofollow sponsored ugc\" title=\"\">Serilog dans ASP.NET Core 3.1-La journalisation structur\u00e9e simplifi\u00e9e<\/a><\/li>\n<\/ul>\n\n\n\n<div class=\"wp-container-6 wp-block-columns alignwide\">\n<div class=\"wp-container-5 wp-elements-e1ba0e3d9d30b7fec5c25e47c471e6ef wp-block-column has-text-color has-background has-link-color\" style=\"background-color:#c0ebf1;color:#000000;padding-top:2em;padding-right:2em;padding-bottom:2em;padding-left:2em\">\n<h2 id=\"patron\" style=\"font-size:40px\"><strong>Vous aimez le contenu&nbsp;?<\/strong><\/h2>\n\n\n\n<p class=\"has-normal-font-size\"><strong>Si vous aimez mes articles, pensez \u00e0 m\u2019acheter quelques caf\u00e9s !<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\">\n\n\n\n<div class=\"wp-container-4 is-horizontal is-content-justification-center wp-block-buttons alignfull\">\n<div class=\"wp-block-button has-custom-width wp-block-button__width-100\"><a class=\"wp-block-button__link has-white-color has-text-color has-background no-border-radius\" href=\"https:\/\/www.buymeacoffee.com\/oussamasaiI\" style=\"background-color:#000000\" target=\"_blank\" rel=\"noreferrer noopener\">Achetez-moi un caf\u00e9<\/a><\/div>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Presque toutes les applications doivent effectuer une sorte de travail de fond. Qu&rsquo;il s&rsquo;agisse d&rsquo;une t\u00e2che longue et fastidieuse ou&#8230; <\/p>\n<div class=\"art-el-more\"><a href=\"https:\/\/oussamasaidi.com\/en\/hangfire-avec-asp-net-core\/\" class=\"art-link art-color-link art-w-chevron\">Read more<\/a><\/div>","protected":false},"author":1,"featured_media":585,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[40,45,41,56,58],"tags":[],"ppma_author":[286],"class_list":["post-584","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-netcore","category-asp-net","category-c","category-c-2","category-hangfire"],"acf":[],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/10\/1-aeY-Tx2cglu6a8YjQ2oBuQ.png","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":660,"url":"https:\/\/oussamasaidi.com\/en\/best-libraries-for-aspnet-core\/","url_meta":{"origin":584,"position":0},"title":"15 meilleures biblioth\u00e8ques pour les d\u00e9veloppeurs ASP.NET Core","author":"Saidi Oussama","date":"November 23, 2022","format":false,"excerpt":"Plusieurs nouveaux d\u00e9veloppeurs font quotidiennement leurs premiers pas dans ASP.Net Core pour leur carri\u00e8re de d\u00e9veloppement Web. Choisir et ma\u00eetriser les meilleures biblioth\u00e8ques qui aident \u00e0 optimiser l'exp\u00e9rience de d\u00e9veloppement est le facteur d\u00e9cisif pour toute technologie. Avec la croissance rapide de .NET Core au cours des derni\u00e8res ann\u00e9es, plusieurs\u2026","rel":"","context":"In &quot;.Net Core&quot;","block_context":{"text":".Net Core","link":"https:\/\/oussamasaidi.com\/en\/category\/netcore\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/02\/pngaaa.com-592393.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/02\/pngaaa.com-592393.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/02\/pngaaa.com-592393.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/02\/pngaaa.com-592393.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/02\/pngaaa.com-592393.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/02\/pngaaa.com-592393.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":399,"url":"https:\/\/oussamasaidi.com\/en\/serilog-in-aspnet-core-3-1\/","url_meta":{"origin":584,"position":1},"title":"Ma\u00eetriser les Logs Structur\u00e9s avec Serilog dans ASP.NET Core 8","author":"Saidi Oussama","date":"September 21, 2022","format":false,"excerpt":"Guide Complet Serilog avec Exemples pour SQL Server et le Cloud Introduction Aujourd'hui, les applications modernes g\u00e9n\u00e8rent des volumes croissants de donn\u00e9es. Pour les d\u00e9velopper efficacement, une solution de journalisation robuste devient indispensable. Parmi les outils disponibles, Serilog se distingue comme l'une des meilleures biblioth\u00e8ques de logging pour .NET. Dans\u2026","rel":"","context":"In &quot;.Net Core&quot;","block_context":{"text":".Net Core","link":"https:\/\/oussamasaidi.com\/en\/category\/netcore\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/07\/serilog-dotnet-core.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/07\/serilog-dotnet-core.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/07\/serilog-dotnet-core.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/07\/serilog-dotnet-core.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/07\/serilog-dotnet-core.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":838,"url":"https:\/\/oussamasaidi.com\/en\/comment-implementer-authentification-cle-api-aspnet-core\/","url_meta":{"origin":584,"position":2},"title":".NET Core : impl\u00e9menter l\u2019authentification par cl\u00e9 API en C#","author":"Saidi Oussama","date":"August 22, 2024","format":false,"excerpt":"ContexteCr\u00e9ation de l'attribut de cl\u00e9 APIImpl\u00e9menter du filtre d'autorisation ApiKeyimpl\u00e9mentation de l'ApiKeyValidatorTester l'APIUtilisez le middlewareConclusionDerniers Articles Vous pouvez trouver le code source complet sur github Contexte Alors, qu\u2019est-ce que l\u2019authentification par cl\u00e9 API dans ASP.NET Core ? Prenons un exemple concret. Imaginez que vous ayez d\u00e9velopp\u00e9 un tableau de bord\u2026","rel":"","context":"In &quot;.Net Core&quot;","block_context":{"text":".Net Core","link":"https:\/\/oussamasaidi.com\/en\/category\/netcore\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2024\/07\/Capture00.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2024\/07\/Capture00.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2024\/07\/Capture00.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":1639,"url":"https:\/\/oussamasaidi.com\/en\/restful-api-mastery-best-practices-with-asp-net-core\/","url_meta":{"origin":584,"position":3},"title":"RESTful API Best Practices with ASP.NET Core","author":"Saidi Oussama","date":"December 16, 2025","format":false,"excerpt":"Professional Best Practices, Versioning Strategies & Advanced Serialization (Part 1) In this blog Introduction: Building Enterprise-Grade RESTful APIs with ASP.NET Core1. RESTful APIs in the Modern ASP.NET Core EcosystemWhy REST Still Dominates2. REST Architectural Constraints Every ASP.NET Core API Must EnforceClient\u2013Server SeparationStatelessnessUniform Interface3. Establishing a Clean and Scalable ASP.NET Core\u2026","rel":"","context":"In &quot;.Net Core&quot;","block_context":{"text":".Net Core","link":"https:\/\/oussamasaidi.com\/en\/category\/netcore\/"},"img":{"alt_text":"RESTful API Mastery","src":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-cover-scaled.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-cover-scaled.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-cover-scaled.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-cover-scaled.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-cover-scaled.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-cover-scaled.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":1714,"url":"https:\/\/oussamasaidi.com\/en\/https-oussamasaidi-com-restful-api-mastery-best-practices-with-asp-net-core-part-2\/","url_meta":{"origin":584,"position":4},"title":"RESTful API best practices\u00a0with ASP.NET Core Part 2","author":"Saidi Oussama","date":"December 20, 2025","format":false,"excerpt":"Testing, Performance, Security, Microservices & Deployment Introduction: From Solid Foundations to Production Excellence In Part 1 of RESTful API Mastery, we established the architectural and technical foundations required to build reliable, evolvable RESTful APIs with ASP.NET Core. However, a well-designed API only becomes truly valuable when it is tested, observable,\u2026","rel":"","context":"In &quot;.Net Core&quot;","block_context":{"text":".Net Core","link":"https:\/\/oussamasaidi.com\/en\/category\/netcore\/"},"img":{"alt_text":"RESTful API Mastery","src":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-2r.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-2r.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-2r.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-2r.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-2r.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2025\/12\/restful-api-mastery-best-practices-with-asp-net-core-2r.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":520,"url":"https:\/\/oussamasaidi.com\/en\/automapper-net-core\/","url_meta":{"origin":584,"position":5},"title":"Premiers pas avec AutoMapper dans ASP.NET Core","author":"Saidi Oussama","date":"October 3, 2022","format":false,"excerpt":"Dans cet article, nous allons apprendre \u00e0 utiliser AutoMapper dans une application ASP.NET Core . Nous allons commencer par examiner ce qu'est AutoMapper et quel probl\u00e8me il r\u00e9sout. Ensuite, nous allons expliquer comment nous pouvons utiliser AutoMapper dans notre application MVC. Apr\u00e8s cela, nous en apprendrons davantage sur les directives\u2026","rel":"","context":"In &quot;.Net Core&quot;","block_context":{"text":".Net Core","link":"https:\/\/oussamasaidi.com\/en\/category\/netcore\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/09\/net-core-automapper.webp?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/09\/net-core-automapper.webp?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/09\/net-core-automapper.webp?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/oussamasaidi.com\/wp-content\/uploads\/2022\/09\/net-core-automapper.webp?resize=700%2C400&ssl=1 2x"},"classes":[]}],"authors":[{"term_id":286,"user_id":1,"is_guest":0,"slug":"oussama_sa","display_name":"Saidi Oussama","avatar_url":{"url":"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/02\/001_001_cv1.jpg","url2x":"https:\/\/oussamasaidi.com\/wp-content\/uploads\/2022\/02\/001_001_cv1.jpg"},"author_category":"1","first_name":"Oussama","last_name":"SAIDI","user_url":"https:\/\/oussamasaidi.com","job_title":"Senior Fullstack .NET Developer","description":"I\u2019m a Senior Fullstack .NET Developer specializing in building scalable, high-performance web applications with .NET, C#, and modern frontend frameworks like React.js. I\u2019m passionate about clean architecture, automated testing, and sharing knowledge through blogs and tutorials."}],"_links":{"self":[{"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/posts\/584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/comments?post=584"}],"version-history":[{"count":1,"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/posts\/584\/revisions"}],"predecessor-version":[{"id":1742,"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/posts\/584\/revisions\/1742"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/media\/585"}],"wp:attachment":[{"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/media?parent=584"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/categories?post=584"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/tags?post=584"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/oussamasaidi.com\/en\/wp-json\/wp\/v2\/ppma_author?post=584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}