【问题标题】:.Net Core Background Services and Long Running Tasks.Net Core 后台服务和长时间运行的任务
【发布时间】:2020-11-20 07:18:54
【问题描述】:

我正在使用 .Net Core 在我的 ASP .Net Core 中运行长时间运行的后台服务和长时间运行的任务,以便获取 Linux Ubuntu 18.04 中外部运行进程生成的文件。使用 FileSystemWatcher。

24 小时或更长时间后,情况会变得更糟。 FileSystemWatch 工作正常,但长时间运行的线程和后台服务不能正常工作,有时它们会停止而没有错误。

任何人都对 .Net Core 3.1 中的后台服务或长时间运行的任务问题有所了解。

我应该使用 Hangfire 来避免这些问题吗?

示例:此线程可以不间断工作长达 72 小时。

   public class DataByteCollector{

    public readonly BytesMemoryCache DataBytesMemoryCache;

    public DataByteCollector(BytesMemoryCache DataBytesMemoryCache)
    {
        DataBytesMemoryCache = DataBytesMemoryCache;
    }

    public BufferBlock<ByteData> ByteStream { get; set; }

    public async Task SubscribeToStream(string bytesId, CancellationToken cancellationToken)
    {
        // Avoid Capturing members in anonymous methods

        var DataBytesMemoryCache = DataBytesMemoryCache;
        ByteStream = new BufferBlock<ByteData>(
            new DataflowBlockOptions
            {
                BoundedCapacity = 8,
                EnsureOrdered = true,
                CancellationToken = cancellationToken
            });
        var byteStream = ByteStream;

        var streamDataCache = DataBytesMemoryCache.GetBytesCache(bytesId);
        if (streamDataCache == null)
        {
            ByteStream.Complete();
            return;
        }

        var bytesData = streamDataCache.Streams;

        async Task DataGathring()
        {
            try
            {
                DateTime? lastDataRead = null;

                var hasStarted = true;
                while (!cancellationToken.IsCancellationRequested && DataBytesMemoryCache.DataCacheExists(bytesId))
                {
                    IEnumerable<ByteData> stat;
                    if (hasStarted)
                    {
                        stat = bytesData.ToArray();
                        hasStarted = false;
                    }
                    else
                    {
                        stat = bytesData.TakeLast(1).Where(x => x.DateTime > lastDataRead).ToArray();
                    }

                    if (stat.Any())
                    {
                        foreach (var farge in stat)
                        {
                            lastDataRead = DateTime.Now;
                            await Channel.SendAsync(farge, cancellationToken);
                        }
                    }
                    else
                    {
                        await byteStream.SendAsync(new ByteData(new byte[100], "dummy"), cancellationToken);
                    }

                 
                    if (lastDataRead == null)
                    {
                        break;
                    }
                    if (lastDataRead < DateTime.Now.AddSeconds(-30))
                    {
                        break;
                    }

                    await Task.Delay(5000, cancellationToken);
                  
                }
                cancellationToken.ThrowIfCancellationRequested();
                byteStream.Complete();
                await byteStream.Completion;
            }
            catch (Exception e)
            {

                byteStream.Complete();
                await byteStream.Completion;
            }
        }

        await Task.Factory.StartNew(DataGathring, cancellationToken);
    }
}

【问题讨论】:

  • 发布您的代码。你是在让人们猜测发生了什么。如果 FSW 将事件发布到由后台服务检查的队列,则不应有任何长时间运行的线程。您是否在后台服务中添加了异常处理和日志记录?这是找出问题所在、哪些事件已处理或未处理、哪些事件失败等的唯一方法
  • 实际代码仍然缺失。无论如何,这不是一个线程,这是一个每 5 秒休眠一次的 task。延续是在线程池线程上处理的,几乎可以肯定每次都会有所不同。该延续是// 省略的代码。那么这段代码有什么作用呢?
  • 如果您想监控长时间运行的作业,您需要跟踪的不仅仅是错误。至少,每次执行的完成,甚至可能是在较低级别的开始。处理时间也很重要。这将允许您跟踪执行的时间和时间,并检测处理时间是否意外增加。
  • 后台/托管服务没有任何问题(它们指的是同一件事)。 Hangfire 提供了更多的调度和监控机制。您还没有发布您的代码,因此无法猜测出什么问题或您正在尝试做什么 - 控制器如何参与后台服务?如果您想将工作从控制器发布到服务,您需要以某种方式连接它们,可能通过队列。 Channel 可用于该工作,让您摆脱循环
  • @PanagiotisKanavos:我必须使用订阅方法..稍后在响应流正文中发送收集的字节“BufferBlock”。

标签: .net asp.net-core .net-core


【解决方案1】:

【讨论】:

  • 因为当用户请求它时我必须在控制器中使用它。
  • @TLEJMI 控制器应该发布到由托管服务监控的队列。我以为这就是你写long-running background Services 时的意思。请求线程打算运行很长时间。
  • @tiejmi 除了通过AddHostedService 注册之外,您还可以将托管服务注册为单例并通过普通 DI 使用它
猜你喜欢
  • 2017-12-14
  • 2020-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
  • 1970-01-01
  • 2023-03-31
  • 2014-10-26
相关资源
最近更新 更多