/// <summary> /// Run the callback in a new thread immediately. If the thread exits with an exception log it but do /// not propogate it. /// </summary> /// <param name="callback">Code for the thread to execute.</param> /// <param name="obj">Object to pass to the thread.</param> /// <param name="name">Name of the thread</param> public static void RunInThread(WaitCallback callback, object obj, string name, bool log = false) { if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest) { Culture.SetCurrentCulture(); callback(obj); return; } ThreadStart ts = new ThreadStart(delegate() { try { Culture.SetCurrentCulture(); callback(obj); } catch (Exception e) { m_log.Error(string.Format("[WATCHDOG]: Exception in thread {0}.", name), e); } finally { try { Watchdog.RemoveThread(log: false); } catch { } } }); StartThread(ts, name, false, log: log); }
private void ProcessRequests() { while (IsRunning || m_jobQueue.Count > 0) { try { CurrentJob = m_jobQueue.Take(m_cancelSource.Token); } catch (ObjectDisposedException e) { // If we see this whilst not running then it may be due to a race where this thread checks // IsRunning after the stopping thread sets it to false and disposes of the cancellation source. if (IsRunning) { throw e; } else { m_log.DebugFormat("[JobEngine] {0} stopping ignoring {1} jobs in queue", Name, m_jobQueue.Count); break; } } catch (OperationCanceledException) { break; } if (LogLevel >= 1) { m_log.DebugFormat("[{0}]: Processing job {1}", LoggingName, CurrentJob.Name); } try { CurrentJob.Action(); } catch (Exception e) { m_log.Error( string.Format( "[{0}]: Job {1} failed, continuing. Exception ", LoggingName, CurrentJob.Name), e); } if (LogLevel >= 1) { m_log.DebugFormat("[{0}]: Processed job {1}", LoggingName, CurrentJob.Name); } CurrentJob = null; } Watchdog.RemoveThread(false); m_finishedProcessingAfterStop.Set(); }