.NET November 1, 2024

From Theory to Practice: Building a File Watcher Service

After understanding the fundamentals of Worker Services, let's explore a practical implementation: a File Watcher Service. This real-world example demonstrates how to apply the concepts we've learned

After understanding the fundamentals of Worker Services, let’s explore a practical implementation: a File Watcher Service. This real-world example demonstrates how to apply the concepts we’ve learned to create a robust, production-ready service.

The Challenge

Imagine you need to monitor a directory for new files, perhaps for processing financial transactions or handling automated data imports. You need a service that:

  • Runs continuously

  • Monitors a specific directory

  • Processes new files as they arrive

  • Maintains security and stability

  • Restarts automatically if it fails

The Solution

Let’s create a File Watcher Service that fulfills these requirements. We’ll build upon our Worker Service knowledge and add file system monitoring capabilities.

Step 1: Basic Structure

First, let’s set up our Worker class with file watching capabilities:

public class Worker : BackgroundService
{
    private readonly ILogger _logger;
    private FileSystemWatcher? _watcher;
    private readonly string _watchPath;
    private readonly string _fileFilter;

    public Worker(ILogger logger, IConfiguration configuration)
    {
        _logger = logger;
        // Get watch path from configuration
        _watchPath = configuration.GetValue("WatchSettings:FolderPath")
            ?? throw new ArgumentNullException("WatchSettings:FolderPath must be set");
        _fileFilter = configuration.GetValue("WatchSettings:FileFilter") ?? "*.txt";
    }
}

Step 2: Configuration

In appsettings.json, we define our watching parameters:

{
  "WatchSettings": {
    "FolderPath": "C:\\WatchFolder",
    "FileFilter": "*.txt"
  }
}

Step 3: Implementing the File Watcher

Now, let’s implement the file watching logic:

public override Task StartAsync(CancellationToken cancellationToken)
{
    _logger.LogInformation("Worker starting at: {time}", DateTimeOffset.Now);
    
    // Ensure directory exists
    if (!Directory.Exists(_watchPath))
    {
        Directory.CreateDirectory(_watchPath);
        _logger.LogInformation("Created watch directory: {path}", _watchPath);
    }

    // Initialize FileSystemWatcher
    _watcher = new FileSystemWatcher
    {
        Path = _watchPath,
        Filter = _fileFilter,
        NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite,
        EnableRaisingEvents = true
    };

    // Hook up events
    _watcher.Created += OnFileCreated;
    _watcher.Error += OnError;

    return base.StartAsync(cancellationToken);
}

Step 4: File Processing Logic

Here’s how we handle new files:

private void OnFileCreated(object sender, FileSystemEventArgs e)
{
    try
    {
        _logger.LogInformation("New file detected: {file}", e.Name);
        
        // Wait briefly to ensure file is completely written
        Thread.Sleep(100);

        // Process the file
        ProcessFile(e.FullPath);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error processing file: {file}", e.Name);
    }
}

Step 5: Service Installation

To install as a Windows Service:

# Create the service
sc.exe create "TSVAutomation" binpath= "C:\path\to\service.exe" start= auto

# Configure automatic restart
sc.exe failure "TSVAutomation" reset= 86400 actions= restart/60000/restart/60000/restart/60000

Applying Best Practices

Our implementation incorporates several best practices:

  1. Configuration Management
  • External configuration in appsettings.json

  • Environment-specific settings support

  • Fail-fast when required settings are missing

  1. Error Handling
  • Graceful handling of file system errors

  • Logging of all important events

  • Proper exception management

  1. Resource Management
  • Proper disposal of FileSystemWatcher

  • Clean shutdown handling

  • Memory-conscious file processing

  1. Reliability
  • Automatic service restart

  • File lock prevention

  • Robust error recovery

Real-World Considerations

When implementing this service in production, consider:

  1. Security
  • Proper file access permissions

  • Secure processing of sensitive data

  • Audit logging for file operations

  1. Performance
  • Batch processing for multiple files

  • Resource throttling

  • Monitoring file processing times

  1. Maintenance
  • Log rotation

  • Performance monitoring

  • Health checks

Connecting the Dots

This implementation demonstrates key Worker Service concepts:

  • Background processing

  • Resource management

  • Error handling

  • Configuration

  • Logging

  • Service lifetime management

The File Watcher Service shows how Worker Services can solve real-world problems by:

  • Providing continuous monitoring

  • Handling system events

  • Processing data reliably

  • Managing resources efficiently

Next Steps

To enhance this service, consider:

  1. Adding file archiving

  2. Implementing retry logic

  3. Adding email notifications

  4. Creating a monitoring dashboard

  5. Implementing health checks

Conclusion

By building this File Watcher Service, we’ve seen how Worker Service concepts translate into practical solutions. This implementation provides a foundation that you can build upon for your specific needs, whether it’s processing financial data, handling system automation, or managing file-based workflows.

Remember: The key to a successful Worker Service is balancing functionality with reliability, security, and maintainability.


Have questions about implementing your own Worker Service? Check our previous guide on Worker Service fundamentals!


Have a .NET modernization project?

Free 30-minute scoping call — no pitch, just a direct conversation about your migration.

Get in touch