上海虹口龙之梦项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

197 lines
5.6 KiB

#if !UNITY_METRO
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UniRx.InternalUtil;
namespace UniRx
{
public static partial class Scheduler
{
public static readonly IScheduler ThreadPool = new ThreadPoolScheduler();
class ThreadPoolScheduler : IScheduler, ISchedulerPeriodic
{
public ThreadPoolScheduler()
{
}
public DateTimeOffset Now
{
get { return Scheduler.Now; }
}
public IDisposable Schedule(Action action)
{
var d = new BooleanDisposable();
System.Threading.ThreadPool.QueueUserWorkItem(_ =>
{
if (!d.IsDisposed)
{
action();
}
});
return d;
}
public IDisposable Schedule(DateTimeOffset dueTime, Action action)
{
return Schedule(dueTime - Now, action);
}
public IDisposable Schedule(TimeSpan dueTime, Action action)
{
return new Timer(dueTime, action);
}
public IDisposable SchedulePeriodic(TimeSpan period, Action action)
{
return new PeriodicTimer(period, action);
}
public void ScheduleQueueing<T>(ICancelable cancel, T state, Action<T> action)
{
System.Threading.ThreadPool.QueueUserWorkItem(callBackState =>
{
if (!cancel.IsDisposed)
{
action((T)callBackState);
}
}, state);
}
// timer was borrwed from Rx Official
sealed class Timer : IDisposable
{
static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();
private readonly SingleAssignmentDisposable _disposable;
private Action _action;
private System.Threading.Timer _timer;
private bool _hasAdded;
private bool _hasRemoved;
public Timer(TimeSpan dueTime, Action action)
{
_disposable = new SingleAssignmentDisposable();
_disposable.Disposable = Disposable.Create(Unroot);
_action = action;
_timer = new System.Threading.Timer(Tick, null, dueTime, TimeSpan.FromMilliseconds(System.Threading.Timeout.Infinite));
lock (s_timers)
{
if (!_hasRemoved)
{
s_timers.Add(_timer);
_hasAdded = true;
}
}
}
private void Tick(object state)
{
try
{
if (!_disposable.IsDisposed)
{
_action();
}
}
finally
{
Unroot();
}
}
private void Unroot()
{
_action = Stubs.Nop;
var timer = default(System.Threading.Timer);
lock (s_timers)
{
if (!_hasRemoved)
{
timer = _timer;
_timer = null;
if (_hasAdded && timer != null)
s_timers.Remove(timer);
_hasRemoved = true;
}
}
if (timer != null)
timer.Dispose();
}
public void Dispose()
{
_disposable.Dispose();
}
}
sealed class PeriodicTimer : IDisposable
{
static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();
private Action _action;
private System.Threading.Timer _timer;
private readonly AsyncLock _gate;
public PeriodicTimer(TimeSpan period, Action action)
{
this._action = action;
this._timer = new System.Threading.Timer(Tick, null, period, period);
this._gate = new AsyncLock();
lock (s_timers)
{
s_timers.Add(_timer);
}
}
private void Tick(object state)
{
_gate.Wait(() =>
{
_action();
});
}
public void Dispose()
{
var timer = default(System.Threading.Timer);
lock (s_timers)
{
timer = _timer;
_timer = null;
if (timer != null)
s_timers.Remove(timer);
}
if (timer != null)
{
timer.Dispose();
_action = Stubs.Nop;
}
}
}
}
}
}
#endif