0

I have a form with animation which i show while doing some requests for other forms. I was doing some research how to show this animated form on requests and come up with doing this:

public partial class ProcessingForm : Form
{
    private static Thread processingFormThread;

    public ProcessingForm()
    {
        InitializeComponent();
    }

    public void StartThreadOnProcessingForm()
    {
        processingFormThread = new Thread(() => { new ProcessingForm().ShowDialog(); });
        processingFormThread.Start();
    }

    public void CloseThreadOnProcessingForm()
    {
        processingFormThread.Abort();
    }
}

and now when i need use the form i do it like this:

public void Foo()
{
    ProcessingForm pf = new ProcessingForm();
    pf.StartThreadOnProcessingForm();
    // some request/data actions
    Form requestForm;
    if (requestdata!= null)
    {
        requestForm = new requestForm(data);
        pf.CloseThreadOnProcessingForm();
        requestForm.Show();
        requestForm.SetDataForForm(requestdata);
    }
}

This seamed like a pretty simple solution, but i haven't seen anything like it while researching,so it feels like I'm doing something wrong. My question is there a better way to do a simple thing like this?

Buggy
  • 135
  • 9

3 Answers3

1

One way to approach this is to pass an Action to your progress form, and to execute that action in a separate thread from the progress form. When the action finishes, you close the progress form.

For example, you could do something like this in your progress form:

public partial class ProgressForm: Form
{
    public ProgressForm(Action action)
    {
        _action = action;
        InitializeComponent();
    }

    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);

        Task.Factory.StartNew(() =>
        {
            _action();
            _finished = true;
            BeginInvoke(new Action(Close));
        });
    }

    protected override void OnClosing(CancelEventArgs e)
    {
        // Prevent the user from closing the form until the action has completed.

        if (!_finished)
            e.Cancel = true;
    }

    private readonly Action _action;
    private volatile bool _finished;
}

Then when you want to wait for an long action to complete, you can use the progress form like so (this example shows the progress form when a button is clicked in the main form, and the action is just a dummy function that sleeps for a few seconds to simulate work):

public partial class Form1: Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        using (var progress = new ProgressForm(action))
        {
            progress.ShowDialog();
        }
    }

    static void action()
    {
        Thread.Sleep(10000);
    }
}
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
0

To be honest, I do not really understand what you are trying to achieve, but there are two obvious problems:

  1. Starting a new thread to call ShowDialog makes no sense. The point of using ShowDialog instead of Show is to create a modal dialog that blocks the execution (of the current thread) until the dialog is closed. Doing that in a new thread defeats the whole purpose.

  2. As noted by Matthew Watson, Abort is bad. See: What's wrong with using Thread.Abort()

I suggest calling ProcessingForm non-modal (Show), make it Topmost and disable the other form (no threads). Then do your data actions in a background Task (async/await). When the task is finished, you close the ProcessingForm and re-enable the other form.

Community
  • 1
  • 1
Sebastian Negraszus
  • 11,915
  • 7
  • 43
  • 70
0

If i understand well you want a popup window that understand when to show and close automatically.

A simple solution is to poll a static property named something like 'Busy' and call Show on form if true and hide if false. You can avoid polling by putting logic in 'Busy' property setter.

From the main app you just set Popup.Busy = true before a long running operation and false when you are done.

Just start the popup in a new thread.

Mauro Sampietro
  • 2,739
  • 1
  • 24
  • 50