using System.Collections.Concurrent;
using System.IO;
using System.Text;
using System.Threading.Channels;
namespace Serein.WorkBench.tool
{
///
/// 可以捕获类库输出的打印输出
///
public class LogTextWriter : TextWriter
{
private readonly Action logAction; // 更新日志UI的委托
private readonly StringWriter stringWriter = new(); // 缓存日志内容
private readonly Channel logChannel = Channel.CreateUnbounded(); // 日志管道
private readonly Action clearTextBoxAction; // 清空日志UI的委托
private int writeCount = 0; // 写入计数器
private const int maxWrites = 500; // 写入最大计数
public LogTextWriter(Action logAction, Action clearTextBoxAction)
{
this.logAction = logAction;
this.clearTextBoxAction = clearTextBoxAction;
// 异步启动日志处理任务,不阻塞主线程
Task.Run(ProcessLogQueueAsync);
}
public override Encoding Encoding => Encoding.UTF8;
public override void Write(char value)
{
stringWriter.Write(value);
if (value == '\n')
{
EnqueueLog();
}
}
public override void Write(string? value)
{
if (string.IsNullOrWhiteSpace(value)) return;
stringWriter.Write(value);
if (value.Contains('\n'))
{
EnqueueLog();
}
}
public override void WriteLine(string? value)
{
if (string.IsNullOrWhiteSpace(value)) return;
stringWriter.WriteLine(value);
EnqueueLog();
}
// 将日志加入通道
private void EnqueueLog()
{
var log = stringWriter.ToString();
stringWriter.GetStringBuilder().Clear();
if (!logChannel.Writer.TryWrite(log))
{
// 如果写入失败(不太可能),则直接丢弃日志或处理
}
}
// 异步处理日志队列
private async Task ProcessLogQueueAsync()
{
await foreach (var log in logChannel.Reader.ReadAllAsync()) // 异步读取日志通道
{
logAction?.Invoke(log); // 执行日志写入到UI的委托
writeCount++;
if (writeCount >= maxWrites)
{
clearTextBoxAction?.Invoke(); // 清空文本框
writeCount = 0; // 重置计数器
}
}
}
}
}