Tools.CQ.LI 1.0.26

Tools.CQ.LI Version:1.0.23

● 修复完成。Attach 现在会遍历 LogKeyCollection(它实现了 IEnumerable)加载已有条目,无论先写日志还是先绑定都能正常显示。

改动点:LogViewerViewModel.cs 的 Attach 方法,在订阅事件前增加了:

  • 清空并重新加载 _allEntries
  • 重建 _availableKeys 列表 94 + 95 _logCollection.EntryAdded += OnEntryAdded; 96 _logCollection.EntryRepeated += OnEntryRepeated; 97 }

● 修复完成。Attach 现在会遍历 LogKeyCollection(它实现了 IEnumerable)加载已有条目,无论先写日志还是先绑定都能正常显示。

改动点:LogViewerViewModel.cs 的 Attach 方法,在订阅事件前增加了:

  • 清空并重新加载 _allEntries
  • 重建 _availableKeys 列表
  • 同步 TotalCount

Tools.CQ.LI Version:1.0.22

重命名重构:Log* → LogKey*

将所有日志相关类型重命名为 LogKey* 前缀,避免与其他库的命名冲突:

  • LogCollectionLogKeyCollection
  • LogEntryLogKeyEntry
  • LogLevelLogKeyLevel
  • LogServiceLogKeyService
  • LogViewerLogKeyViewer
  • LogLevelConverterLogKeyLevelConverter
  • LogLevelToBrushConverterLogKeyLevelToBrushConverter

修复 SelectedKey 过滤时滚动偏移错误

SelectedKey"All" 时,从头部移除的条目可能不在当前过滤视图中,导致 savedOffset - RemovedCount 过度补偿,滚动位置偏移错误。修复后 _removedCount 仅对通过 FilterEntry 检查的可见条目计数。


日志控件(最小 Demo)

C# ViewModel:

using Tools.CQ.LI.Service;

LogKeyService logService = LogKeyService.CreateOrGet("MyApp");
logService.IntervalMs = 1000;  // 重复去重间隔(ms)

LogKeyCollection Logs { get; set; } = logService.Logs;

// 任意线程写入
logService.WriteLine("Thread.A", "数据处理完成", LogKeyLevel.Warn);
logService.WriteLine("Thread.B", "发生错误", LogKeyLevel.Error);

XAML:

<controls:LogKeyViewer Height="500" LogCollection="{Binding Logs}" />

数据上传

var influx = new InfluxUploadService(new InfluxOptions
{
    Enabled = true,
    Url = "http://127.0.0.1:8086",
    Database = "energy"
});

statistics.SetData(...);

// 一行上传
influx.Upload(statistics);

延时

// 使用示例
public class Program
{
    public static void Main()
    {
        try
        {
            Console.WriteLine("开始精准延时测试...");

            // 测试10ms延时
            long start = PreciseDelay.GetTimestamp();
            PreciseDelay.SpinWait(10);
            long elapsed = PreciseDelay.GetTimestamp() - start;
            Console.WriteLine($"请求10ms延时,实际延时: {elapsed}ms");

            // 测试100ms延时
            start = PreciseDelay.GetTimestamp();
            PreciseDelay.BusyWait(100);
            elapsed = PreciseDelay.GetTimestamp() - start;
            Console.WriteLine($"请求100ms延时,实际延时: {elapsed}ms");

            // 测试自适应延时
            start = PreciseDelay.GetTimestamp();
            PreciseDelay.AdaptiveDelay(50);
            elapsed = PreciseDelay.GetTimestamp() - start;
            Console.WriteLine($"请求50ms自适应延时,实际延时: {elapsed}ms");

            // 测试带取消功能的延时
            var cts = new CancellationTokenSource();
            Task.Run(() =>
            {
                Thread.Sleep(20);
                cts.Cancel();
            });

            start = PreciseDelay.GetTimestamp();
            bool completed = PreciseDelay.SpinWaitWithCancellation(100, cts.Token);
            elapsed = PreciseDelay.GetTimestamp() - start;
            Console.WriteLine($"带取消的100ms延时: 完成={completed}, 实际时间={elapsed}ms");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"错误: {ex.Message}");
        }
    }
}
// 精准延时 5ms
PrecisionDelay.DelayMilliseconds(5);

// 精准延时 1ms
PrecisionDelay.DelayMilliseconds(1);

// 多线程安全
Parallel.For(0, 4, _ =>
{
    PrecisionDelay.DelayMilliseconds(10);
});

No packages depend on Tools.CQ.LI.

.NET Framework 4.8

Version Downloads Last updated
1.0.34 3 05/12/2026
1.0.33 3 05/06/2026
1.0.32 2 05/06/2026
1.0.31 1 04/29/2026
1.0.30 2 04/29/2026
1.0.29 1 04/29/2026
1.0.28 3 04/29/2026
1.0.26 1 04/29/2026
1.0.25 2 04/29/2026
1.0.24 1 04/29/2026
1.0.23 2 04/29/2026
1.0.22 1 04/29/2026
1.0.21 3 04/23/2026
1.0.20 4 04/17/2026
1.0.19 6 04/10/2026
1.0.18 5 04/08/2026
1.0.17 4 04/08/2026
1.0.16 8 03/30/2026
1.0.15 8 03/27/2026
1.0.14 16 02/26/2026
1.0.12 10 02/25/2026
1.0.11 10 02/25/2026
1.0.10 15 02/10/2026
1.0.9 14 02/10/2026
1.0.8 14 02/10/2026
1.0.6 14 02/10/2026
1.0.5 15 02/10/2026
1.0.4 14 02/10/2026
1.0.3 15 02/10/2026
1.0.2 13 02/10/2026
1.0.1 15 02/10/2026
1.0.0 14 02/10/2026