public static IProgressEvents StartAsync(IServiceProvider sp, IProgressControlHost host, Func<IProgressController, ProgressStepDefinition[]> stepFactory) { if (sp == null) { throw new ArgumentNullException(nameof(sp)); } if (host == null) { throw new ArgumentNullException(nameof(host)); } if (stepFactory == null) { throw new ArgumentNullException(nameof(stepFactory)); } Debug.Assert(ThreadHelper.CheckAccess(), "Expected to be called on the UI thread"); // Initialize a controller and an observer var controller = new SequentialProgressController(sp); controller.Initialize(stepFactory(controller)); IVsOutputWindowPane sonarLintPane = VsShellUtils.GetOrCreateSonarLintOutputPane(sp); bool logFullMessage; #if DEBUG logFullMessage = true; #else logFullMessage = false; #endif var notifier = new VsOutputWindowPaneNotifier(sp, sonarLintPane, ensureOutputVisible: true, messageFormat: Strings.UnexpectedWorkflowError, logFullException: logFullMessage); controller.ErrorNotificationManager.AddNotifier(notifier); Observe(controller, host); controller.RunOnFinished(r => observedControllersMap.Remove(controller)); #pragma warning disable 4014 // We do want to start and forget. All the errors will be forwarded via the error notification manager controller.Start(); #pragma warning restore 4014 return controller; }