<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nick Proud</title>
    <description>The latest articles on Forem by Nick Proud (@nick_proud).</description>
    <link>https://forem.com/nick_proud</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2150702%2F78bced04-ff78-4d28-9efa-5ea5ddc185e2.jpg</url>
      <title>Forem: Nick Proud</title>
      <link>https://forem.com/nick_proud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nick_proud"/>
    <language>en</language>
    <item>
      <title>Building a Background Worker Service in .NET</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Tue, 25 Feb 2025 08:59:08 +0000</pubDate>
      <link>https://forem.com/nick_proud/building-a-background-worker-service-in-net-97g</link>
      <guid>https://forem.com/nick_proud/building-a-background-worker-service-in-net-97g</guid>
      <description>&lt;p&gt;When developing applications, there are times when you need to run background processes that execute independently of user interactions. Whether it's automating tasks, handling scheduled operations, or processing data at intervals, .NET Worker Services provide an efficient solution. In this post, we’ll explore what Worker Services are, how they work, and how to implement a simple example that periodically calls an API and saves the data to a local file.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a .NET Worker Service?
&lt;/h2&gt;

&lt;p&gt;A Worker Service in .NET is a background application that runs continuously, executing logic in a loop with a specified delay. Unlike web applications or interactive services, Worker Services are designed to operate autonomously, making them ideal for automation scenarios where tasks need to be performed at regular intervals.&lt;/p&gt;

&lt;p&gt;Common use cases for Worker Services include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Background data processing&lt;/li&gt;
&lt;li&gt;Automated API polling&lt;/li&gt;
&lt;li&gt;Scheduled task execution&lt;/li&gt;
&lt;li&gt;System monitoring and logging&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting Up a Worker Service in .NET
&lt;/h2&gt;

&lt;p&gt;To create a Worker Service, follow these steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create a New Worker Service Project
&lt;/h3&gt;

&lt;p&gt;Open &lt;strong&gt;Visual Studio&lt;/strong&gt;, select &lt;strong&gt;Create a new project&lt;/strong&gt;, and search for &lt;strong&gt;Worker Service&lt;/strong&gt;. Choose the &lt;strong&gt;C# Worker Service template&lt;/strong&gt; and proceed with the default settings. For this example, name the project &lt;code&gt;APICallerService&lt;/code&gt; and use &lt;strong&gt;.NET 8&lt;/strong&gt; (the latest LTS version at the time of writing).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Understanding the Worker Class
&lt;/h3&gt;

&lt;p&gt;The core logic of a Worker Service is defined in the &lt;code&gt;Worker.cs&lt;/code&gt; file. This class extends &lt;code&gt;BackgroundService&lt;/code&gt;, which allows it to run continuously in the background. Let’s break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;ExecuteAsync&lt;/code&gt; method contains a &lt;strong&gt;while loop&lt;/strong&gt; that runs indefinitely unless a cancellation request is received.&lt;/li&gt;
&lt;li&gt;The loop includes a delay (&lt;code&gt;Task.Delay&lt;/code&gt;), defining how often the logic should run.&lt;/li&gt;
&lt;li&gt;Logging is used to output messages indicating the execution state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the default structure of a Worker Service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BackgroundService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsCancellationRequested&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Worker running at: {time}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateTimeOffset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Customizing the Worker Service
&lt;/h3&gt;

&lt;p&gt;For our example, we'll modify the Worker Service to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Call an API every &lt;strong&gt;5 seconds&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Save the response to a local file.&lt;/li&gt;
&lt;li&gt;Log each API request and response.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Define the API Endpoint
&lt;/h4&gt;

&lt;p&gt;We will use &lt;strong&gt;JSONPlaceholder&lt;/strong&gt; (a free fake API for testing) to fetch &lt;strong&gt;To-Do items&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ApiUrl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://jsonplaceholder.typicode.com/todos/1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Implement API Call and File Writing
&lt;/h4&gt;

&lt;p&gt;Modify &lt;code&gt;ExecuteAsync&lt;/code&gt; to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch data from the API using &lt;code&gt;HttpClient&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write the JSON response to a local file.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 5 seconds&lt;/span&gt;

    &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Service started at: {time}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateTimeOffset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsCancellationRequested&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Contacting API..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetStringAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ApiUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;filePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"data.json"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAllTextAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data saved successfully at {time}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateTimeOffset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error fetching API data: {error}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Running the Worker Service
&lt;/h3&gt;

&lt;p&gt;To run the Worker Service, press &lt;strong&gt;F5&lt;/strong&gt; in Visual Studio. The application will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log messages to indicate execution progress.&lt;/li&gt;
&lt;li&gt;Fetch data from the API every 5 seconds.&lt;/li&gt;
&lt;li&gt;Save the data to &lt;code&gt;data.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example log output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO] Service started at 2024-02-25T12:00:00Z
[INFO] Contacting API...
[INFO] Data saved successfully at 2024-02-25T12:00:05Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Worker Services in .NET offer a simple yet powerful way to run background tasks. In this post, we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduced Worker Services and their use cases.&lt;/li&gt;
&lt;li&gt;Created a Worker Service in .NET.&lt;/li&gt;
&lt;li&gt;Implemented an API polling mechanism with logging and file storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this foundation, you can extend the Worker Service to include error handling, database integration, or even advanced scheduling.&lt;/p&gt;




&lt;p&gt;If you found this guide helpful, &lt;a href="https://youtube.com/@nickproudprogrammer" rel="noopener noreferrer"&gt;subscribe to my YouTube channel&lt;/a&gt;&lt;br&gt;
 for more .NET tutorials!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>csharp</category>
      <category>dotnet</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
