Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics

Dashboard
Notifications
Mark all as read
Q&A

Which abstraction should I choose for background services and why?

+6
−1

Which concept is best for managed background services?

1. RunAsync(CancellationToken):

interface IWorker
{
    Task RunAsync(CancellationToken cancellationToken = default);
}

...

IWorker worker = ...;
var source = new CancellationTokenSource();
_ = worker.RunAsync(source.Token);

// And when it's time to shutdown the worker:
source.Cancel();

vs

2. RunAsync and StopAsync

interface IWorker
{
    Task RunAsync();
    Task StopAsync();
}

...

IWorker worker = ...;
_ = worker.RunAsync();

// And when it's time to shutdown the worker:
await worker.StopAsync();
Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

2 comments

"Best" in what way? Derek Elkins‭ 6 months ago

It's probably worth noting that these don't provide equivalent interfaces. In particular, the CancellationToken approach does not provide you with a way of telling when the cancellation is "complete". The second interface would be closer to the former if StopAsync returned void (at which point Stop would be a better name). If you need this functionality, then the first interface isn't an option, at least not naively used. Derek Elkins‭ 6 months ago

1 answer

+4
−0

I will provide an answer from a pragmatic perspective, rather than a direct answer to your question. This is particularly important when working on a real project (as opposed to homework).

Short answer

Try to use a third-party library instead of reinventing the wheel. Defining and managing background jobs can be harder than expected due to aspects such as integration with the existing codebase, monitoring, cancellation, exception handling (retrial strategy). One such library in the .NET world (classic + Core) is Hangfire.

Longer answer

Unless you are just toying with background services or tasks, these will have to integrate into a bigger project and besides the implementation details will become more important:

  • concurrency - what should happen if a job does not end and another instance starts? Should overlap be allowed?
  • retrials - sometimes the job fails. Does a retrial make sense?
  • analytics - is there a need to keep a history related to how jobs ran (time, errors etc.)?
  • job information persistence - does it make sense to persist the job information (i.e. scheduling information) somewhere like a database?
  • dependency injection - if tasks are related to already existing functionality, this must be "injected", so there is also the overhead of making background services work the DI container

I am sure there are many other aspects, but the bottom line is that unless this is just for educational purposes, a third-party library will take care of many of the above aspects and more.

Why does this post require moderator attention?
You might want to add some details to your flag.

0 comments

Sign up to answer this question »