Moved to Task instead of Thread for main function and provided better error symantics.

master
Sean McArdle 2017-08-22 14:27:18 -07:00
parent b82ea094f6
commit de8d834372
2 changed files with 54 additions and 21 deletions

View File

@ -86,6 +86,7 @@ USAGE
{
case OperatingMode.service:
ServiceExecutionMode = ServiceExecutionMode.Service;
CanStop = true;
Run(new[] { this });
break;
@ -99,7 +100,7 @@ USAGE
Console.WriteLine("Starting Service...");
OnStart(args);
OnStartCommandLine();
OnStop();
Stop();
break;
case OperatingMode.install:
@ -133,11 +134,7 @@ USAGE
AppDomain.CurrentDomain.UnhandledException += OnCurrentDomainUnhandledException;
}
protected virtual void OnStartCommandLine()
{
Console.WriteLine("Service is running... Hit ENTER to break.");
Console.ReadLine();
}
protected abstract void OnStartCommandLine();
protected abstract void OnStartImpl(string[] args);

View File

@ -25,8 +25,9 @@ namespace WifiSitter
internal volatile static NetworkState netstate;
private const string _serviceName = "WifiSitter";
private Guid _uninstGuid;
private Thread _mainLoopThread;
private Thread _mqServerThread;
private Task _mainLoopTask;
private Task _mqServerTask;
private List<TaskSupervisor> _monitoredTask = new List<TaskSupervisor>();
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private volatile bool _paused;
private SynchronizationContext _sync;
@ -289,7 +290,7 @@ namespace WifiSitter
}
private void WorkerThreadFunc() {
while (!_shutdownEvent.WaitOne(0)) {
if (_paused) {
@ -364,7 +365,10 @@ namespace WifiSitter
}
}
private volatile bool _nics_reset = false;
private void ResetNicState (NetworkState netstate) {
if (_nics_reset) return;
if (netstate == null)
return;
@ -537,34 +541,66 @@ namespace WifiSitter
Intialize();
var syncContext = (SynchronizationContext.Current != null)
? TaskScheduler.FromCurrentSynchronizationContext()
: TaskScheduler.Current;
// Setup background thread for running main loop
LogLine("Spawning main thread...");
_mainLoopThread = new Thread(WorkerThreadFunc);
_mainLoopThread.Name = "WifiSitter Main Loop";
_mainLoopThread.IsBackground = true;
_mainLoopThread.Start();
_mainLoopTask = new Task(WorkerThreadFunc);
_mainLoopTask.ContinueWith((worker) => {
if (worker.IsFaulted) {
WriteLog(LogType.error,
"Error in main main worker:\n{0}",
String.Join("\n", worker?.Exception?.InnerExceptions?.Select(
x => String.Format("{0} : {1}", x.TargetSite, x.Message))) ?? "Cannot get exception.");
_shutdownEvent.Set();
Stop();
}
}, syncContext);
try {
_mainLoopTask.Start();
}
catch (Exception e) {
WriteLog(LogType.error, "Exception in main task:\n{0}", _mainLoopTask.Exception.Message);
}
// Setup 0mq message router task
if (Properties.Settings.Default.enable_ipc) {
LogLine(LogType.info, "Initializing IPC worker thread...");
_mqServerThread = new Thread(ZeroMQRouterRun);
_mqServerThread.Name = "0MQ Server Thread";
_mqServerThread.IsBackground = true;
_mqServerThread.Start();
_mqServerTask = new Task(ZeroMQRouterRun);
_mqServerTask.ContinueWith((worker) => {
if (worker.IsFaulted) {
WriteLog(LogType.error, "Error in main 0mq router:\n\t{1} : {0}",
String.Join("\n", worker?.Exception?.InnerExceptions?.Select(
x => String.Format("{0} : {1}", x.TargetSite, x.Message))) ?? "Cannot get exception.");
}
}, syncContext);
_mqServerTask.Start();
}
else { WriteLog(LogType.warn, "IPC not initialized. May not communicate with GUI agent."); }
}
catch (Exception e) {
WriteLog(LogType.error, e.Source + " {0}", e.Message);
}
}
protected override void OnStartCommandLine() {
Console.WriteLine("Service is running... Hit CTRL+C to break.");
bool run = true;
Console.CancelKeyPress += (o, e) => { run = false; };
while (run) {
if ((bool)_shutdownEvent?.WaitOne(10)) { run = false; }
};
}
protected override void OnStopImpl() {
ResetNicState(netstate);
LogLine("Stopping now...");
_shutdownEvent.Set();
if (!_mainLoopThread.Join(3000)) {
_mainLoopThread.Abort();
}
ResetNicState(netstate);
}
protected override void OnPause() {