微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在backgroundservice中运行Task.Run意外停止工作

如何解决在backgroundservice中运行Task.Run意外停止工作

我在backgroundservice内部使用Task.Run。我有后台服务,负责特定系统的登录和发送HeartBeat。

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;
    }

}

初始化方法以尝试登录系统,如果成功,则需要启动SendHeartBeat。 SendHeartBeat方法负责获取成功或失败。如果成功,我会将Mustlogon的值更改为false,并每10秒发送一次SendHeartBeat。 SendHeartBeat的并行处理我需要调用_testService.StartProcessAsync从流中获取数据。它以某种方式停止工作,并再次启动logon,但是我需要它直到返回false为止,它应该可以工作,并且SendHeartBeat需要每10秒完成一次,但是不幸的是,如果出现bool res = true,它会停止工作,而此时此刻不起作用抛出任何异常。有什么建议吗?

解决方法

这是我根据BackgroundService base class中的链接想到的,并“插入”了您所需的功能:(当然,未经测试)

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;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?