/// <summary> /// Request a client-side abort of a given transaction. /// </summary> /// <param name="handle">The execution handle of the request to cancel.</param> /// <returns>True if the abort succeeded, false if it was already too late (and the request completed or timed /// out before the abort could be processed).</returns> internal bool ExecuteCancelAsync <T>(AsyncResponse <T> handle) { // Validate connection status. // Note: We're not throwing anything, just returning immediately if the connection was closed (failure // already caused the abort callback) if (this.Status != ConnectionStatus.Connected) { return(false); } // Get the response from the stack. Response response = this.ExecutionCache.BeginRemoveItem(handle.ExecutionId); // If the response wasn't already dealt with, finalize processing. if (response != null) { // Trigger the callback. The call is non-blocking: the callback is queued for execution in the // ThreadPool. response.OnExecutionAbort(); // Call completion handler for classes that provide additional tracking. this.OnExecutionComplete( handle.ExecutionId , response.Procedure , response.ExecutionDuration , ResponseStatus.Aborted , 0 // Not accurate: the response might come later, but since we'll drop it... ); // Return true to indicate the request was aborted return(true); } // Return false to indicate it was already too late to abort the request. return(false); }
/// <summary> /// Terminates the connection and closes all resources. /// </summary> internal void Terminate() { // Mark connection as closed this.Status = ConnectionStatus.Closed; // Stop background threads - swallow any undue exception... try { // Kill the threads, the stream. try { if (this.OwnsCallbackExecutor) { this.CallbackExecutor.Stop(); } this.BackgroundNetworkThread.Abort(); this.BackgroundTimeoutThread.Abort(); this.BaseStream.Close(); } catch { } // Trigger all callbacks on executions we will not be able to fulfill. try { long[] killList = this.ExecutionCache.GetCurrentItems(); while (killList.Length > 0) { foreach (long expiredExecutionId in killList) { // Get the response from the stack Response response = this.ExecutionCache.BeginRemoveItem(expiredExecutionId); // If the response wasn't already dealt with, finalize processing. if (response != null) { // Trigger the callback. The call is non-blocking: the callback is queued for // execution in the ThreadPool. response.OnExecutionAbort(); // Call completion handler for classes that provide additional tracking. this.OnExecutionComplete( expiredExecutionId , response.Procedure , response.ExecutionDuration , response.Status , 0 // Not accurate: the response might come later... ); } } Thread.Sleep(10); killList = this.ExecutionCache.GetCurrentItems(); } } catch { } // Freeze statistics so the elapsed time doesn't report nonsensical figures. if (this.Settings.StatisticsEnabled) { lock ((this.Stats as IDictionary).SyncRoot) foreach (KeyValuePair <string, Statistics> pair in this.Stats) { pair.Value.Freeze(); } this.LifetimeStats.Freeze(); } // Trace as needed. if (this.Settings.TraceEnabled) { VoltTrace.TraceEvent( TraceEventType.Information , VoltTraceEventType.ConnectionClosed , Resources.TraceConnectionClosed , this.ServerHostId , this.ConnectionId ); } } catch { } }