Esempio n. 1
0
 public void QueueOp(AssetOp op)
 {
     if (_threadAborted)
     {
         throw new Exception("Thread has already been aborted for this op manager!");
     }
     op.SetStatus(OpStatus.Queued);
     _opQueue.Enqueue(op);
     OpStatusChanged?.Invoke(this, op);
     lock (_threadLock)
     {
         if (_thread != null && !_thread.IsAlive)
         {
             Log.LogErr("Thread in opmanager was stopped but not null!");
             try
             {
                 _thread.Abort();
                 _opQueue.Where(x => x.Status == OpStatus.Started).ToList().ForEach(x => {
                     x.SetStatus(OpStatus.Failed, new Exception("Op was in a Started state when the thread died.  Failing it."));
                     Log.LogErr("Op was found in a started state while the thread had died!");
                 });
                 _thread = null;
             }
             catch
             { }
         }
         if (_thread == null)
         {
             _thread = new Thread(WorkerThreadProc);
             _thread.Start();
         }
     }
     _queueEvent.Set();
 }
Esempio n. 2
0
        private void OpManager_OpStatusChanged(object sender, QuestomAssets.AssetOps.AssetOp e)
        {
            List <AssetOp> opCopy;

            lock (_trackedOps)
            {
                if (!_trackedOps.Any(x => x.ID == e.ID))
                {
                    _trackedOps.Add(e);
                }

                _trackedOps.RemoveAll(x => x.Status == OpStatus.Complete);

                opCopy = _trackedOps.ToList();
            }

            HostOpStatus opstat = new HostOpStatus();

            foreach (var op in opCopy)
            {
                string exmsg = null;
                //if (op.Exception != null)
                //{
                //    exmsg = $"{op.Exception.Message} {op.Exception.StackTrace}";
                //    var ex = op.Exception.InnerException;
                //    while (ex != null)
                //    {
                //        exmsg += $"\nInnerException: {ex.Message} {ex.StackTrace}";
                //        ex = ex.InnerException;
                //    }
                //}
                opstat.Ops.Add(new HostOp()
                {
                    ID = op.ID, OpDescription = op.GetType().Name, Status = op.Status, Error = op.Exception?.Message
                });
            }
            lock (_sendClientOpsChangedLock)
            {
                if (_sendClientOpsChanged == null)
                {
                    _sendClientOpsChanged            = new Debouncey <HostOpStatus>(400, false);
                    _sendClientOpsChanged.Debounced += (e2, a) =>
                    {
                        SendMessageToClient(a);
                    };
                }
            }
            if (e.Status == OpStatus.Complete && e.IsWriteOp)
            {
                CurrentConfig.IsCommitted = CurrentConfig.IsCommitted && (!Engine.HasChanges);
                SendConfigChangeMessage();
            }
            _sendClientOpsChanged.EventRaised(this, opstat);
        }
Esempio n. 3
0
        private void OpManager_OpStatusChanged(object sender, QuestomAssets.AssetOps.AssetOp e)
        {
            List <AssetOp> opCopy;

            lock (_trackedOps)
            {
                if (!_trackedOps.Any(x => x.ID == e.ID))
                {
                    _trackedOps.Add(e);
                }

                _trackedOps.RemoveAll(x => x.Status == OpStatus.Complete);

                opCopy = _trackedOps.ToList();
            }

            HostOpStatus opstat = new HostOpStatus();

            foreach (var op in opCopy)
            {
                string exmsg = null;
                //if (op.Exception != null)
                //{
                //    exmsg = $"{op.Exception.Message} {op.Exception.StackTrace}";
                //    var ex = op.Exception.InnerException;
                //    while (ex != null)
                //    {
                //        exmsg += $"\nInnerException: {ex.Message} {ex.StackTrace}";
                //        ex = ex.InnerException;
                //    }
                //}
                opstat.Ops.Add(new HostOp()
                {
                    ID = op.ID, OpDescription = op.GetType().Name, Status = op.Status, Error = op.Exception?.Message
                });
            }
            lock (_sendClientOpsChangedLock)
            {
                if (_sendClientOpsChanged == null)
                {
                    _sendClientOpsChanged            = new Debouncey <HostOpStatus>(400, false);
                    _sendClientOpsChanged.Debounced += (e2, a) =>
                    {
                        lock (lastSendOpsLock)
                        {
                            lastOpsSendHadOps = (a.Ops.Count > 0);
                            SendMessageToClient(a);
                        }
                    };
                }
            }
            if (e.Status == OpStatus.Complete && e.IsWriteOp)
            {
                CurrentConfig.IsCommitted = CurrentConfig.IsCommitted && (!Engine.HasChanges);
                SendConfigChangeMessage();
            }
            //if the last send didn't have ops and this one does, send the message immediately in addition to debouncing it.
            //  this will send a duplicate message because the debounce is called in addition to the message being sent, but it'll assure keeping things in sync with the client
            lock (lastSendOpsLock)
            {
                if ((opstat.Ops.Count > 0) && !lastOpsSendHadOps)
                {
                    lastOpsSendHadOps = true;
                    SendMessageToClient(opstat);
                }
            }
            _sendClientOpsChanged.EventRaised(this, opstat);
        }
Esempio n. 4
0
        private void WorkerThreadProc(object o)
        {
            bool entered = false;

            //I *think* this covers all the race conditions where the thread would stop as an item was being enqueued, probably need to re-review
            try
            {
                do
                {
                    if (_threadAborted)
                    {
                        Log.LogMsg("Opmanager worker thread has been aborted");
                        return;
                    }
                    AssetOp op             = null;
                    bool    dequeued       = false;
                    bool    threadAborting = false;

                    dequeued = _opQueue.TryDequeue(out op);
                    if (!dequeued)
                    {
                        if (entered)
                        {
                            Log.LogMsg("trying to exit on thread " + Thread.CurrentThread.ManagedThreadId);
                            Monitor.Exit(_context.Manager);
                            entered = false;
                        }
                        _queueEvent.WaitOne(2000);
                        continue;
                    }
                    if (!entered)
                    {
                        entered = Monitor.TryEnter(_context.Manager);
                        if (!entered)
                        {
                            continue;
                        }
                        Log.LogMsg("entered on thread " + Thread.CurrentThread.ManagedThreadId);
                    }
                    try
                    {
                        Stopwatch sw = new Stopwatch();
                        op.SetStatus(OpStatus.Started);
                        OpStatusChanged?.Invoke(this, op);
                        Log.LogMsg($"AssetOpManager starting op of type {op.GetType().Name}");
                        sw.Start();
                        op.PerformOp(_context);
                        sw.Stop();
                        Log.LogMsg($"AssetOpManager completed op of type {op.GetType().Name} in {sw.ElapsedMilliseconds}ms");
                        op.SetStatus(OpStatus.Complete);
                        OpStatusChanged?.Invoke(this, op);
                    }
                    catch (ThreadAbortException)
                    {
                        //just die if being aborted
                        _thread        = null;
                        threadAborting = true;
                        Log.LogMsg("Op thread aborting");
                        return;
                    }
                    catch (Exception ex)
                    {
                        Log.LogErr($"Error handling Op type {op.GetType()}, operation threw an exception.", ex);
                        op.SetStatus(OpStatus.Failed, ex);
                    }
                    finally
                    {
                        if (!threadAborting)
                        {
                            OpStatusChanged?.Invoke(this, op);
                        }
                    }
                } while (true);
            }
            catch (ThreadAbortException)
            {
                //Thread aborting, so let it
                Log.LogErr("Op manager thread is aborting");
                _thread = null;
                return;
            }
            catch (Exception ex)
            {
                Log.LogErr("Exception in op manager's worker thread proc!", ex);
            }
            finally
            {
                if (entered)
                {
                    Monitor.Exit(_context.Manager);
                }
                //just to make sure it gets set null in all cases
                _thread = null;
            }
        }