【发布时间】: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