You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I used a Dialog as a progress/busy indicator for some long-running operations in an application. The Dialog is displayed using ShowModalAsync, locking the parent Form/Dialog, while allowing the application code to start the long running operation and eventually Close the dialog and wait for the ShowModalAsync task to complete and Dispose the form. This seems to work fine sometimes, but breaks down when the operation completes synchronously.
I have tried to wait for the OnShown event to be raised before calling the Close/Dispose methods, and while this seems to work for Wpf it does not seem like a reliable solution, causing different effects on Gtk and possibly not working at all on Mac (#2254).
Is the use of a Dialog as a programmatically controlled progress/busy indicator acceptable? Would there be a better approach to achieve the desired behavior?
Expected Behavior
The dialog opens, blocking the main UI, and closes immediately after, or does not show at all.
A Dialog that is asynchronously initialized after Close or Dispose has been called, should just abort the initialization or immediately close after initialization
Actual Behavior
On Wpf: I have seen a NullReferenceException and an InvalidOperationException stating that the window was already closed. This error happens on the next UI iteration (RunIteration/MessageBox/main UI loop).
On Gtk: If Dispose is used, a NullReferenceException occurs on the next UI iteration. If Close is used, the Dialog Shown event is raised before the dialog is actually visible. A subsequent MessageBox appears first, and then the Dialog appears, raising another Shown event. The dialog does not close.
On XamMac/Mac64: Using Dispose results in a NullReferenceException on the UI thread; using Close leaves the Dialog open and manually closing the Dialog results in the main window still being blocked, using Close via AsyncInvoke has no effect.
Steps to Reproduce the Problem
Run the test code below and click the button in the form that appears.
Enabling the form.Close call and running on the Wpf platform produce slightly different results.
(Scheduling the form.Close call on the UI thread seems to work for now)
using Eto.Forms;
using System;
namespace Test {
class Program {
[STAThread]
public static void Main(string[] args) {
new Application(Eto.Platforms.Gtk).Run(new TestForm()); return;
}
class TestForm : Form {
public TestForm() {
Content = new Button() { Command = new Command(ButtonClick) };
}
async void ButtonClick(object state, EventArgs e) {
var form = new Dialog();
_ = form.ShowModalAsync(this);
//Application.Instance.AsyncInvoke(form.Close);
//form.Close();
form.Dispose();
MessageBox.Show(this, "hi");
}
}
}
}
Specifications
Version: 2.8.2
Platform(s): WPF, Gtk, XamMac2, Mac64
Operating System(s): Windows 10, Mac OS 13.1
The text was updated successfully, but these errors were encountered:
why would you not await the ShowModalAsync? Why not just use ShowModal?
not awaiting a UI element and then disposing of it while its still trying to build that UI element would of course cause issues.
why would you not await the ShowModalAsync? Why not just use ShowModal?
I am using the modal as a busy/progress indicator, so I need to start other processing once the modal is visible. Awaiting ShowModalAsync or calling ShowModal would block the thread until the user closes the window, and not allow for other work to be done.
not awaiting a UI element and then disposing of it while its still trying to build that UI element would of course cause issues.
Partially due to #2254 there does not seem to be a reliable way to find out when the UI element is ready and can be disposed of. I have tried to effectively run the work in/after the OnShown callback, but that did not yield reliable results either.
For comparison, Windows Forms allows to attach a form to a parent, show the form in a way that blocks only while the UI is being built and allowing the form to be disposed of immediately after.
Largely due to there being no reliable callback/event it seems to be impossible to close a modal immediately after its creation, regardless of whether the call to ShowModalAsync is awaited or not. Eto Forms could also handle this attempt better by either aborting the UI construction or scheduling its destruction if Dispose/Close is called before the UI element is fully constructed.
I used a Dialog as a progress/busy indicator for some long-running operations in an application. The Dialog is displayed using ShowModalAsync, locking the parent Form/Dialog, while allowing the application code to start the long running operation and eventually Close the dialog and wait for the ShowModalAsync task to complete and Dispose the form. This seems to work fine sometimes, but breaks down when the operation completes synchronously.
I have tried to wait for the OnShown event to be raised before calling the Close/Dispose methods, and while this seems to work for Wpf it does not seem like a reliable solution, causing different effects on Gtk and possibly not working at all on Mac (#2254).
Is the use of a Dialog as a programmatically controlled progress/busy indicator acceptable? Would there be a better approach to achieve the desired behavior?
Expected Behavior
The dialog opens, blocking the main UI, and closes immediately after, or does not show at all.
Actual Behavior
Steps to Reproduce the Problem
Specifications
The text was updated successfully, but these errors were encountered: