I am using Task.Run inside backgroundservice. I have backgroundservice which is responsible for LogOn and Send HeartBeat for a specific system.
public class TestBGService : IHostedService
{
private readonly ITestService _testService;
private bool MustLogOn { get; set; } = true;
private string id { get; set; }
public TestBGService(ITestService testService)
{
_testService = testService;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
Log.Information("TestBGService starts Initialize");
await Initialize();
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private async Task Initialize()
{
try
{
if (MustLogOn)
{
Log.Information("TestBGService ExecuteAsync trying to LogOnAsync");
id = await _testService.LogOnAsync();
if (!string.IsNullOrEmpty(id))
{
Log.Information($"new id equals to {id}");
MustLogOn = false;
_ = Task.Run(async () =>
{
while (true)
{
bool res = await SendHeartBeat(id);
Log.Information($"res from SendHeartBeat {res}");
if (!res)
{
break;
}
await Task.Delay(10000);
}
});
await _testService.StartProcessAsync(id);
}
}
}
catch (Exception ex)
{
Log.Error($"TestBGService ExecuteAsync throws {ex.ToString()}");
}
}
private async Task<bool> SendHeartBeat(string id)
{
bool isSuccess = true;
try
{
Log.Information("TestBGService sending heartbeat at " + DateTime.Now);
var response = new HeartBeatResponseModel();
response = await _testService.SendHeartBeatAsync(id);
Log.Information("TestBGService heartbeat response equals to " + response.IsSuccessful);
if (!response.IsSuccessful)
{
MustLogOn = true;
isSuccess = response.IsSuccessful;
}
}
catch (Exception ex)
{
Log.Error(ex, "TestBGService SendHeartBeat throws");
isSuccess = false;
MustLogOn = true;
}
return isSuccess;
}
}
Initialize method trying LogOn to system and in the success case, it needs to start to SendHeartBeat. SendHeartBeat method is responsible for getting success or failure. In case of success, I am changing the value of MustLogon to false and sending SendHeartBeat every 10 seconds. Parallel for SendHeartBeat I need to call _testService.StartProcessAsync to get data from the stream. Somehow it stops working and it starts LogOn again but I need that until it returns false it should work and SendHeartBeat needs to be done every 10 seconds but unfortunately, it stops working in case of bool res = true and this moment it does not throw any exceptions. Any suggestions?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
This is what I came up with following the link from BackgroundService base class and “plug in” your required functionality: (untested, of course)
public class TestBGService : BackGroundService
{
// I guess you are using different logging
private readonly ILogger<TestBGService> _logger;
// Your service to send Heartbeats to
private readonly ITestService _testService;
// If id is null, we need to login.
private string _id = null;
public TestBGService (ILogger<TestBGService> logger, ITestService testService)
{
_logger = logger;
_testService = testService ?? throw new ArgumentNullException(nameof(testService));
}
public Task StartAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("TestBGService running.");
return Task.CompletedTask;
}
// This will be triggered by the runtime.
private async Task ExecuteAsync (System.Threading.CancellationToken stoppingToken)
{
while( !stoppingToken.CancellationRequested )
{
try
{
if( string.IsNullOrEmpty(_id) )
{
// _id is null => perform login
_id = await _testService.LogOnAsync(); // perhaps pass stoppingToken?
}
bool res = await SendHeartBeat(id); // again: consider passing stoppingToken
if( !res ) _id = null; // Heartbeat unsuccessful: login next time
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
}
catch(Exception ex) // You should actually catch more specific exceptions.
{
// TODO log Exception
_id = null; // Reset id, so we login next time.
}
}
}
private async Task<bool> SendHeartBeat(string id)
{
// Don't even try if login was unsuccessful.
if ( string.IsNullOrEmpty(id) ) return false;
_logger.LogInformation("TestBGService sending heartbeat at {0}" , DateTime.Now);
var response = await _testService.SendHeartBeatAsync(id);
_logger.LogInformation("TestBGService heartbeat response {0}successful", response.IsSuccessful ? "" : "un");
return response.IsSuccessful;
}
public Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("TestBGService is stopping.");
// TODO maybe explicit logout?
return Task.CompletedTask;
}
}
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0