private static void WatchFaces(string directory, bool debug, Machine machine) { var lastSeen = new Dictionary <string, DateTime>(); var repeatTime = double.Parse(config["faceRepeatSeconds"]); var watcher = new FileSystemWatcher(directory) { IncludeSubdirectories = true, EnableRaisingEvents = true }; var wait = new EventWaitHandle(false, EventResetMode.AutoReset); string imagePath = null; watcher.Created += (_, e) => { imagePath = e.FullPath; wait.Set(); if (debug) { Console.WriteLine($"Image: {imagePath}"); } }; (new Thread(new ThreadStart(() => { while (true) { wait.WaitOne(); if (debug) { Console.WriteLine($"Face reco {imagePath}"); } byte[] image = null; var attempt = 3; do { try { image = File.ReadAllBytes(imagePath); break; } catch (Exception) { Thread.Sleep(100); // file lock } } while (attempt-- > 0); if (image != null) { foreach (var f in faces.RecoFaces(image, debug)) { if (debug) { Console.WriteLine($"Recognized {f}"); } var last = lastSeen.ContainsKey(f) ? lastSeen[f] : DateTime.MinValue; if ((DateTime.Now - last).TotalSeconds > repeatTime) { var key = $"faceGreeting.{f}"; var cmd = config.ContainsKey(key) ? config[key] : config["faceGreeting.default"]; machine.Execute(String.Format(cmd, f)); } else { if (debug) { Console.WriteLine(" Already seen recently..."); } } lastSeen[f] = DateTime.Now; } } } })) { IsBackground = true }).Start(); }