private int InternalSend(int waitTime, IEnumerable <string> identities, string eventName, params string[] arguments) { int count = 0; using (WaitAndContinueList work = new WaitAndContinueList()) { foreach (string identity in Check.NotNull(identities)) { IpcEventMessage m = new IpcEventMessage(this, ExecutionTimeout, identity, eventName, arguments); if (!m.Completed) { work.AddWork(m); } else { count += m.Successful ? 1 : 0; } } if (!work.IsEmpty) { //Waiting while in-call results in dead-locks, so we force these to defer if they do not complete immediatly if (InCall) { waitTime = 0; } System.Diagnostics.Stopwatch timer = null; if (waitTime > 0) { timer = new System.Diagnostics.Stopwatch(); timer.Start(); } IWaitAndContinue waitItem; int ticksRemaining = waitTime; while (work.PerformWork(ticksRemaining, out waitItem)) { count += ((IpcEventMessage)waitItem).Successful ? 1 : 0; if (waitTime > 0 && (ticksRemaining = (int)(waitTime - timer.ElapsedMilliseconds)) < 0) { break; } } if (!work.IsEmpty) { WaitAndContinueWorker worker = _deferred; if (worker != null) { try { worker.AddWork(work); } catch (ObjectDisposedException) { } } } } } return(count); }
/// <summary> /// Shutsdown the worker thread created by a call to EnableAsyncSend() allowing up to /// the number of milliseconds in timeout to shutdown the worker and complete any /// pending work. If timeout is 0, the worker will be aborted. /// </summary> public void StopAsyncSending(bool completeWork, int timeout) { WaitAndContinueWorker kill; lock (_sync) { kill = _deferred; _deferred = null; } if (kill != null) { using (kill) kill.Complete(completeWork, timeout); } }
/// <summary> /// Enables a background worker thread to continue sending messages that are incomplete /// after the expiration of the timeout specified in the Broadcast/SendTo method. This /// is required to avoid dead-locks if your broadcasting messages within an IpcEvent.OnEvent /// event handler. /// </summary> public void EnableAsyncSend() { lock (_sync) _deferred = _deferred ?? new WaitAndContinueWorker(); }