Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
Fix workflows run from the command line not exiting upon completion.
Browse files Browse the repository at this point in the history
This also indirectly fixes exceptions during cleanup getting swallowed unceremoniously.
Also fixes leaked NotifyIcon.

Fixes bonsai-rx#1740
  • Loading branch information
PathogenDavid committed Apr 23, 2024
1 parent 9357b9e commit d0e74e9
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions Bonsai.Editor/WorkflowRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,33 @@ editorSettings.Tag is ExpressionBuilder builder &&
contextMenu.Items.Add(new ToolStripSeparator());
contextMenu.Items.Add(new ToolStripMenuItem("Stop", null, (sender, e) => cts.Cancel()));

var notifyIcon = new NotifyIcon();
using var notifyIcon = new NotifyIcon();
notifyIcon.Icon = Properties.Resources.Icon;
notifyIcon.Text = Path.GetFileName(fileName);
notifyIcon.ContextMenuStrip = contextMenu;
notifyIcon.Visible = true;

var synchronizationContext = new WindowsFormsSynchronizationContext();
runtimeWorkflow.Finally(() =>
{
notifyIcon.Visible = false;
Application.Exit();
// Posting the exit to the main thread's winforms sync context is important for two reasons:
// 1) If this finally action will be executed on the main thread (IE: the workflow is empty) we need to
// defer Application.Exit until Application.Run, otherwise we're trying to exit a message loop which
// has not even started.
// 2) When this finally action executes it will be on a background thread. While Application.Exit can
// be called from any thread, many FormClosed callbacks within Bonsai assume they're running on the
// main thread. Application.Exit invokes the FormClose (and FormClosing) callbacks directly.
//
// As an added bonus this also ensures any exceptions thrown via Application.Exit (especially those
// within FormClose/FormClosing handlers) will be observed as exceptions thrown in a finally action
// are silently swallowed.
synchronizationContext.Post(_ => Application.Exit(), null);
}).Subscribe(
unit => { },
ex => { Console.Error.WriteLine(ex); },
() => { },
cts.Token);

Application.Run();
}

Expand Down

0 comments on commit d0e74e9

Please sign in to comment.