question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

StatusBar fix exposes big issue...Lack of Dispose

See original GitHub issue

In https://github.com/migueldeicaza/gui.cs/pull/685, I caused a bug on exiting scenarios.

The problem is, within the StatusBar constructor we connect up to Application.Resized

Application.Resized += (e) => {

This event subscription never gets removed, so even after the status bar has been destroyed this code gets called.

In order to fix this correctly, the View class heirarchy needs to support Disposable, I think,

I just built a POC to illustrate it, but it feels like a much deeper change than I’m comfy throughing together on a saturday morning. For now I’m going to hack around it to ensure that when the event handler is called nothing bad happens.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7

github_iconTop GitHub Comments

1reaction
migueldeicazacommented, Jun 15, 2020

Adding Disposable is fine, but I think that this surfaces one of the things that I hate most about the event programming in C#, which is that these things can leak and generally consume too much memory.

I wonder if we should instead encourage folks to either subclass Application and catch a proper virtual method for “Resize”, or using a delegate pattern for the event.

1reaction
tigcommented, Jun 14, 2020

@migueldeicaza , while we have your attention:

I have convinced myself the Responder class hierarchy needs formal IDisposable support.

I have written a POC that adds IDisposable to Responder and then modified Application and a few other key places to call Dispose on subviews appropriately.

e.g. here’s View.Dispose:

protected override void Dispose (bool disposing)
{
	foreach (var subview in InternalSubviews) {
		subview.Dispose ();
	}

	base.Dispose (disposing);
}

I added this to Responder:

#if DEBUG
		/// <summary>
		/// For debug purposes to verify objects are being disposed properly
		/// </summary>
		public bool WasDisposed = false;
		public static List<Responder> Instances = new List<Responder> ();
		public Responder ()
		{
			Instances.Add (this);
		}
#endif 

and used this to show it was working:

[Fact]
public void Run_All_Sceanrios ()
{
	List<Type> scenarioClasses = Scenario.GetDerivedClasses<Scenario> ();
	Assert.NotEmpty (scenarioClasses);

	foreach (var scenarioClass in scenarioClasses) {
		// Setup some fake kepresses 
		// Passing empty string will cause just a ctrl-q to be fired
		Console.MockKeyPresses.Clear ();
		int stackSize = CreateInput ("");
		int iterations = 0;
		Application.Iteration = () => {
			iterations++;
			// Stop if we run out of control...
			if (iterations > 10) {
				Application.RequestStop ();
			}
		};
		Application.Init (new FakeDriver (), new NetMainLoop (() => FakeConsole.ReadKey (true)));

		var ms = 1000;
		var abortCount = 0;
		Func<MainLoop, bool> abortCallback = (MainLoop loop) => {
			abortCount++;
			Application.RequestStop ();
			return false;
		};
		var token = Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (ms), abortCallback);

		var scenario = (Scenario)Activator.CreateInstance (scenarioClass);
		scenario.Init (Application.Top, Colors.Base);
		scenario.Setup ();
		scenario.Run ();

		Application.Shutdown ();

		Assert.Equal (0, abortCount);
		// # of key up events should match # of iterations
		Assert.Equal (1, iterations);
		Assert.Equal (stackSize, iterations);
	}

	foreach (var inst in Responder.Instances) {
		Assert.True (inst.WasDisposed);
	}
}

What do you think of adding this? I think we need it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Dispose statusBarItem if there is no more message #320
At present, after sync extension displayed some message and then cleared the message after timeout, the statusBarItem still holds a place. This ...
Read more >
issue with iOS7
Not every developer is sitting on a ton of money to throw at every problem. It's the very rare app that solve major...
Read more >
Customize the Application Status Bar
If your status bar customization doesn't show, you may be using and outdated version of OutSystems UI. Try updating OutSystems UI from Forge....
Read more >
tqdm in Jupyter Notebook prints new progress bars ...
The print statement is outputting a number (~0.89) in between each status bar update, which is messing up the output. Try removing the...
Read more >
Python Progress Bar
A value at 1 or bigger represents 100% def update_progress(progress): barLength = 10 # Modify this to change the length of the progress...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found