protected virtual void Dispose(bool disposing)
 {
     if (!_disposed && disposing)
     {
         _logger.LogDebug("Disposing FunctionDispatcher");
         _workerErrorSubscription.Dispose();
         _workerRestartSubscription.Dispose();
         _processStartCancellationToken.Cancel();
         _processStartCancellationToken.Dispose();
         _jobHostLanguageWorkerChannelManager.ShutdownChannels();
         State     = FunctionInvocationDispatcherState.Disposed;
         _disposed = true;
     }
 }
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (_disposing)
                {
                    _logger.LogDebug("Disposing FunctionDispatcher");
                    _disposeToken.Cancel();
                    // We're explicitly NOT disposing the token here, because if anything our Task.Delay() is waiting on it
                    // Disposing here gives zero time to observe the cancel and is likely to yield an ObjectDisposeException in a race.
                    // Since this is relatively rare, let the GC clean it up.
                    //_disposeToken.Dispose();
                    _startWorkerProcessLock.Dispose();
                    _workerErrorSubscription.Dispose();
                    _workerRestartSubscription.Dispose();
                    _processStartCancellationToken.Cancel();
                    _processStartCancellationToken.Dispose();
                    _jobHostLanguageWorkerChannelManager.ShutdownChannels();
                }

                State     = FunctionInvocationDispatcherState.Disposed;
                _disposed = true;
            }
        }