MES-ETL/MesETL.App/Services/DataRecordQueue.cs

64 lines
1.7 KiB
C#
Raw Normal View History

2023-12-28 15:18:03 +08:00
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
2024-02-09 19:08:57 +08:00
using TaskExtensions = MesETL.App.Helpers.TaskExtensions;
2023-12-28 15:18:03 +08:00
namespace MesETL.App.Services;
2023-12-28 15:18:03 +08:00
2024-01-04 09:00:44 +08:00
/// <summary>
/// 数据队列
/// </summary>
2023-12-29 16:16:05 +08:00
public class DataRecordQueue : IDisposable
2023-12-28 15:18:03 +08:00
{
2023-12-29 16:16:05 +08:00
private readonly BlockingCollection<DataRecord> _queue;
2023-12-28 15:18:03 +08:00
2024-02-09 19:08:57 +08:00
private long _currentCharCount;
private readonly long _maxCharCount = 2_147_483_648; // 4GiB
2023-12-29 16:16:05 +08:00
public int Count => _queue.Count;
public bool IsCompleted => _queue.IsCompleted;
public bool IsAddingCompleted => _queue.IsAddingCompleted;
2023-12-28 15:18:03 +08:00
2023-12-29 16:16:05 +08:00
public event Action? OnRecordWrite;
public event Action? OnRecordRead;
2024-02-09 19:08:57 +08:00
public DataRecordQueue() : this(500_000, 2_147_483_648) // 默认容量最大500K
2023-12-28 15:18:03 +08:00
{
2024-01-29 09:29:16 +08:00
}
2024-02-09 19:08:57 +08:00
public DataRecordQueue(int boundedCapacity, long maxCharCount)
2024-01-29 09:29:16 +08:00
{
_queue = new BlockingCollection<DataRecord>(boundedCapacity);
2024-02-09 19:08:57 +08:00
_maxCharCount = maxCharCount;
2023-12-28 15:18:03 +08:00
}
2024-02-09 19:08:57 +08:00
public void CompleteAdding() => _queue.CompleteAdding();
2023-12-29 16:16:05 +08:00
public bool TryDequeue([MaybeNullWhen(false)] out DataRecord record)
2023-12-28 15:18:03 +08:00
{
2023-12-29 16:16:05 +08:00
if (_queue.TryTake(out record))
{
2024-02-09 19:08:57 +08:00
Interlocked.Add(ref _currentCharCount, -record.FieldCharCount);
2023-12-29 16:16:05 +08:00
OnRecordRead?.Invoke();
return true;
}
2023-12-28 15:18:03 +08:00
2023-12-29 16:16:05 +08:00
return false;
2023-12-28 15:18:03 +08:00
}
2023-12-29 16:16:05 +08:00
2024-02-09 19:08:57 +08:00
public async Task EnqueueAsync(DataRecord record)
2023-12-28 15:18:03 +08:00
{
2024-02-09 19:08:57 +08:00
var charCount = record.FieldCharCount;
if(_currentCharCount + charCount > _maxCharCount)
await TaskExtensions.WaitUntil(() => _currentCharCount + charCount < _maxCharCount, 50);
2023-12-29 16:16:05 +08:00
_queue.Add(record);
2024-02-09 19:08:57 +08:00
Interlocked.Add(ref _currentCharCount, charCount);
2023-12-29 16:16:05 +08:00
OnRecordWrite?.Invoke();
2023-12-28 15:18:03 +08:00
}
2023-12-29 16:16:05 +08:00
public void Dispose()
{
_queue.Dispose();
}
2023-12-28 15:18:03 +08:00
}