CPF/CPF/Threading/DispatcherTimer.cs
2023-11-21 23:05:03 +08:00

214 lines
6.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
namespace CPF.Threading
{
/// <summary>
/// 主窗体存在的时候才有效
/// </summary>
public class DispatcherTimer : IDisposable
{
TimeSpan interval;
public DispatcherTimer()
{
interval = TimeSpan.FromMilliseconds(15);//毫秒
}
static Thread timeThread;
static List<DispatcherTimer> timers;
static List<DispatcherTimer> tempTimers;
static object _lock = new object();
public void Stop()
{
if (isEnabled)
{
lock (_lock)
{
isEnabled = false;
timers.Remove(this);
}
}
}
public void Start()
{
if (isEnabled)
{
return;
}
nextTick = CPF.Platform.Application.Elapsed + Interval;
if (timeThread == null)
{
timers = new List<DispatcherTimer>();
tempTimers = new List<DispatcherTimer>();
timeThread = new Thread(SetTime) { IsBackground = true, Name = "定时器线程" };
timeThread.Start();
}
lock (_lock)
{
timers.Add(this);
isEnabled = true;
//cancellationTokenSource.Cancel(true);
}
}
TimeSpan nextTick;
//static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
//static int delay = 100;
static ManualResetEvent timeMre = new ManualResetEvent(false);
/// <summary>
/// 用于提高定时器精度,主线程有任意消息时候调用
/// </summary>
public static void SetTimeTick()
{
timeMre.Set();
}
static void SetTime()
{
while (true)
{
timeMre.WaitOne(1);
timeMre.Reset();
//Thread.Sleep(1);
//Thread.SpinWait(10000);
//#if Net4
// var task = TaskEx.Delay(delay, cancellationTokenSource.Token);
//#else
// var task = Task.Delay(delay, cancellationTokenSource.Token);
//#endif
// task.Wait();
//TimeSpan? nextDelay = null;
var now = CPF.Platform.Application.Elapsed;
lock (_lock)
{
foreach (var t in timers)
{
if (t.isEnabled && t.nextTick <= now)
{
tempTimers.Add(t);
//if (nextDelay == null || t.nextTick < nextDelay.Value)
// nextDelay = t.nextTick;
}
}
}
if (tempTimers.Count > 0)
{
if (CPF.Platform.Application.Main != null)
{
Dispatcher.MainThread.Invoke(() =>
{
foreach (var t in tempTimers.ToArray())
{
if (t.Tick != null)
{
t.Tick(t, EventArgs.Empty);
}
if (t.IsEnabled)
{
t.nextTick = CPF.Platform.Application.Elapsed + t.Interval;
//if (nextDelay == null || t.nextTick < nextDelay.Value)
// nextDelay = t.nextTick;
}
else
{
lock (_lock)
{
timers.Remove(t);
}
}
}
});
}
tempTimers.Clear();
}
//if (nextDelay != null)
//{
// delay = Math.Max(2, (int)(nextDelay.Value - _clock.Elapsed).TotalMilliseconds);
//}
}
}
public TimeSpan Interval
{
get
{
return interval;
}
set
{
interval = value;
}
}
bool isEnabled;
public bool IsEnabled
{
get
{
return isEnabled;
}
set
{
if (value)
{
Start();
}
else
{
Stop();
}
}
}
public object Tag { get; set; }
public event EventHandler Tick;
#region IDisposable Support
private bool disposedValue = false; // 要检测冗余调用
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
Tick = null;
if (disposing)
{
// TODO: 释放托管状态(托管对象)。
Stop();
}
// TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
// TODO: 将大型字段设置为 null。
disposedValue = true;
}
}
// TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
~DispatcherTimer()
{
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
Dispose(false);
}
// 添加此代码以正确实现可处置模式。
public void Dispose()
{
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
Dispose(true);
// TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
// GC.SuppressFinalize(this);
}
#endregion
}
}