Skip to content

Instantly share code, notes, and snippets.

@JKamsker
Created April 14, 2017 22:10
Show Gist options
  • Save JKamsker/d0c4e5838c6f29b6b0664fc799d5061f to your computer and use it in GitHub Desktop.
Save JKamsker/d0c4e5838c6f29b6b0664fc799d5061f to your computer and use it in GitHub Desktop.
Watches constantly on the result of a func and executes an action if true
internal class BwHelper
{
public object SessObj { get; set; }
public Func<object, bool> CheckingAlg { get; set; }
public Action<bool, object> StatusChange { get; set; }
public bool doCallbackOn { get; set; }
public bool lastResult { get; set; }
public double NextCheck { get; set; }
public double Interval { get; set; }
}
internal class BoolWatcher
{
public static Stopwatch SW { get => GetBoolWatcher().sw; }
private Stopwatch sw = Stopwatch.StartNew();
private List<BwHelper> _internalTickList = new List<BwHelper>();
private static BoolWatcher _BW;
private AutoResetEvent _ae = new AutoResetEvent(false);
private bool KillMe { get => _killMeSwitch; set { _killMeSwitch = value; _ae.Set(); } }
private bool _killMeSwitch;
private BoolWatcher()
{
Thread th = new Thread(ThreadWork)
{
IsBackground = true,
};
th.Start();
}
public static BoolWatcher GetBoolWatcher()
{
if (_BW == null)
{
_BW = new BoolWatcher();
}
return _BW;
}
public int AddWatcher<T>(T SessionObject, Func<T, bool> CheckingAlgorithm, Action<bool, T> StatusChangeCallBack, double Interval, bool callBackOn) //;where T : class, new()
{
int returnVal = -1;
lock (_internalTickList)
{
if (typeof(T) is object || SessionObject is object)
{
var AddVar = SessionObject as object;
_internalTickList.Add(new BwHelper()
{
SessObj = SessionObject,
CheckingAlg = a => (CheckingAlgorithm((T)a)),
StatusChange = (a, b) => StatusChangeCallBack(a, (T)b),
doCallbackOn = callBackOn,
lastResult = !callBackOn
});
returnVal = _internalTickList.Count - 1;
_ae.Set();
}
}
return returnVal;
}
public void RemoveWatcher(int JobID)
{
lock (_internalTickList)
{
_internalTickList[JobID] = null;
}
}
public void RemoveWatcher(object Job)
{
lock (_internalTickList)
{
var ids = _internalTickList.Select((a, i) => a != null && a.SessObj == Job ? i : -1).Where(m => m != -1).ToArray();
for (int i = 0; i < ids.Length; i++)
{
_internalTickList[ids[i]] = null;
}
}
}
private void ThreadWork()
{
int rTw = 0;
while (!KillMe)
{
var ElapsedTime = sw.Elapsed.TotalMilliseconds;
var tlQuery = _internalTickList.Where(m => m != null);
int? ToWait = int.MaxValue;
lock (_internalTickList)
{
if (tlQuery.Any())
{
ToWait = (int)(tlQuery.Min(m => m.NextCheck) - ElapsedTime);
}
else
{
ToWait = null;
}
}
if (ToWait == null)
{
_ae.WaitOne();
}
else
{
rTw = (int)ToWait;
if (rTw > 0)
{
_ae.WaitOne(rTw);
}
}
if (KillMe)
return;
ElapsedTime = sw.Elapsed.TotalMilliseconds;
lock (_internalTickList)
{
var ToExec = tlQuery.Where(m => m.NextCheck - ElapsedTime <= 2).ToArray();
for (int i = 0; i < ToExec.Length; i++)
{
var item = ToExec[i];
var result = item.CheckingAlg(item.SessObj);
if (result != item.lastResult && result == item.doCallbackOn)
{
item.lastResult = result;
item.StatusChange(result, item.SessObj);
}
}
}
}
}
}
@JKamsker
Copy link
Author

Sample usage:
bw.AddWatcher(explorer, a => a.Busy == false, (a, b) =>
{
Console.WriteLine("UnBusy " + BoolWatcher.SW.Elapsed.TotalMilliseconds);
try
{
//It could be that its busy
if (b != null && !b.Busy)
{
BoolWatcher.GetBoolWatcher().RemoveWatcher(b);
onFoundNotBusy?.Invoke(b);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}, 1, true);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment