user13290160
user13290160

Reputation:

How to run backgroundservices on seperate thread?

I realized that background services blocks main thread and suddenly it makes latency in my main thread.I can't find useful resources about how to make backgroundservices to not make latency and block main thread.Any suggestions?

public Task StartAsync(CancellationToken cancellationToken)
{
    _timer = new Timer(DoWork, null, 0, 10000);
    Initialize().GetAwaiter();

    return Task.CompletedTask;
}

private async void DoWork(object state)
{
    try
    {
        //some logic
        await testService.DoWorkAsync();
    }
    catch (Exception ex)
    {
        Log.Error(ex, "TestBackgroundService DoWork throws ");
    }
}


private async Task Initialize()
{
    while (true)
    {
        try
        {
            if (IsEnabled)
            {
                //some logic
                await testService.PrintAsync();
                IsEnabled = false;
            }
            else
            {
                //some logic
                await testService.CloseAsync();
                if (condition)
                {
                    IsEnabled = true;
                }
            }
            await Task.Delay(1000);
        }
        catch (Exception ex)
        {
            Log.Error($"ExecuteAsync throws {ex.ToString()}");
        }
    }
}

Upvotes: 3

Views: 1847

Answers (2)

rmbl
rmbl

Reputation: 39

You have to use it the right way and I think scoped background task is what you want:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio#consuming-a-scoped-service-in-a-background-task

Here you have a ExecuteAsync Method and you could use it like this:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    
    while (!stoppingToken.IsCancellationRequested)
    {
        //your code

        await DoWork(stoppingToken);
        Task.Delay(1000);
    }
}

Upvotes: 1

Catalin
Catalin

Reputation: 11721

If it is possible, you can create an Controller for the background jobs.

From your code, you can simply invoke the controller action using an HttpClient method.

private async Task ExecuteJobAsync(string jobName)
{
    // background job
    string uri = $"http://localhost:21454/api/jobs/{jobName}";

    using (HttpClient client = new HttpClient())
    {
        using (HttpContent content = new StringContent(string.Empty, Encoding.UTF8, "application/json"))
        {
            using (HttpResponseMessage response = await httpClient.PostAsync(uri, content).ConfigureAwait(false))
            {

            }
        }
    }
}

Invoking background job:

private async Task Initialize()
{
    while (true)
    {
        try
        {
            if (IsEnabled)
            {
                await ExecuteJobAsync("print");
                IsEnabled=false;
            }
            else
            {
                //some logic
                await ExecuteJobAsync("close");
                
                if(condition){
                    IsEnabled=true;
                }
            }
            
            await Task.Delay(1000);
        }
        catch (Exception ex)
        {
            Log.Error($"ExecuteAsync throws {ex.ToString()}");
        }
    }
}

Jobs controller:

[Route("api/jobs")]
public class JobsController : Controller
{
    [HttpPost("print")]
    public void PrintAction()
    {
        // code
    }

    [HttpPost("close")]
    public void CloseAction()
    {
        // code
    }
}

Upvotes: 0

Related Questions