# stop method

1. @override

FutureOr<void> stop([

1. Runnable? callback

])
override

Stop this component, typically in a synchronous fashion.

Should not throw an exception if the component is not running.

The callback is used to enable asynchronous shutdown. Implementations should call the callback once their shutdown process is complete.

## Parameters

- `callback`: A callback to invoke once shutdown is complete (may be null)

## Implementation Notes

- If shutdown is synchronous, call the callback immediately
- If shutdown is asynchronous, call the callback when complete
- Always call the callback, even if it's null (null-safe call)

## Implementation

    @override
    FutureOr<void> stop([Runnable? callback]) {
      return synchronized(_lock, () async {
        if (_isRunning) {
          final stoppingMethods = List.from(_lifecycleMethods.where((m) => m.hasDirectAnnotation<OnApplicationStopping>()));

          for(final method in stoppingMethods) {
            final cls = method.getDeclaringClass();
            final instance = cls.isAbstract() ? null : cls.getNoArgConstructor()?.newInstance();

            final arguments = <String, Object?>{};
            final parameters = method.getParameters();
            final contextArgName = parameters.find((p) => _isAssignableFromApplicationContext(p.getClass()))?.getName();

            if(contextArgName != null) {
              arguments[contextArgName] = this;
            }

            method.invoke(instance, arguments);
          }

          _isRunning = false;
          await publishEvent(ContextStoppedEvent.withClock(this, () => DateTime.now()));

          await doStop();

          final stoppedMethods = _lifecycleMethods.where((m) => m.hasDirectAnnotation<OnApplicationStopped>());

          for(final method in stoppedMethods) {
            final cls = method.getDeclaringClass();
            final instance = cls.isAbstract() ? null : cls.getNoArgConstructor()?.newInstance();

            final arguments = <String, Object?>{};
            final parameters = method.getParameters();
            final contextArgName = parameters.find((p) => _isAssignableFromApplicationContext(p.getClass()))?.getName();

            if(contextArgName != null) {
              arguments[contextArgName] = this;
            }

            method.invoke(instance, arguments);
          }
        }

        callback?.run();
      });
    }