0

I am programming a Windows form using C#. I have a waitform that I want to use when I am retrieving data from SQL. For example, I have a button called Refresh. When I press this button, it retrieves the data from the database again. So when I press the refresh button, the waitform opens and the data is loaded in the background. When the data loading is finished, the waitform will close.

Here is my code;

private void RefreshButton_Click(object sender, EventArgs e)
{
    
    using (WaitForm waitForm = new WaitForm())
    {
        
        Thread thread = new Thread(() => LoadData());
        
        thread.Start(waitForm);
        
        waitForm.ShowDialog();
    }
}

private void LoadData()
{
    // Some Entitys
}

in here because of waitForm.ShowDialog() my waitForm never close

Mervan
  • 3
  • 2
  • 1
    E.g., change `private void LoadData((Form win) { // do stuff then... win.BeginInvoke(delegate { win.DialogResult = DialogResult.OK; }); }` and call it as `Thread thread = new Thread(() => LoadData(waitForm));` – Jimi Jan 05 '23 at 18:45
  • It's probably better if you pass an `IProgress` delegate to a Task (a Thread would do anyway), and call the `Progress` delegate's `Report()` method when the Task / Thread completes, then set the DialogResult in the method delegate (which is executed in the UI Thread). This form of callback executes its code no matter the dialog (as, e.g., the `Tick` event of a Timer) – Jimi Jan 05 '23 at 18:56
  • @Jimi I tried this but it doesn't work still problem continiue – Mervan Jan 05 '23 at 20:52
  • 1
    What is *this*? First or second method? Where's the code you wrote in either case? Did you also try the answer you already have? – Jimi Jan 05 '23 at 20:55
  • You can make a global variable for `waitingform` call then end of `LoadData` call `BeginInvoke(() => waitForm.Close());` on `waitinform`. If you dont want waitingform to be in memory, after close 'watingform = null' then GC will clean up. – lork6 Jan 05 '23 at 22:21
  • Use a CodeConverter to change this to C# https://stackoverflow.com/a/13486676/495455 – Jeremy Thompson Jan 06 '23 at 01:56

1 Answers1

0

One of many ways to show a Winform waiting panel is to run the LoadData method on a Task and give the WaitFormWaitingPanel the ability to manage its own visibility.

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        buttonLoadData.Click += onClickLoadData;
    }

    private async void onClickLoadData(object? sender, EventArgs e)
    {
        using (var waitForm = new WinFormWaitingPanel(this))
        {
            await Task.Run(() => LoadData());
        }
    }
    private void LoadData()
    {
        // Mock "any" long-running synchronous task
        // (SQL or otherwise)
        Thread.Sleep(TimeSpan.FromSeconds(1));
    }
}

Example

Semi-transparent wait form covers main form and provides wait cursor.

screenshot

class WinFormWaitingPanel : Form
{
    public WinFormWaitingPanel(Form owner)
    {
        Owner = owner;
        
        // Size this form to cover the main form's client rectangle.
        Size = Owner.ClientRectangle.Size;
        FormBorderStyle = FormBorderStyle.None;
        UseWaitCursor = true;
        StartPosition = FormStartPosition.Manual;
        Location = PointToClient(
            Owner.PointToScreen(Owner.ClientRectangle.Location));

        // Add a label that says "Loading..."
        var label = new Label
        {
            Text = "Loading...",
            TextAlign = ContentAlignment.MiddleCenter,
            Dock = DockStyle.Fill,
        };
        Controls.Add(label);

        // Set the form color to see-through Blue
        BackColor = Color.LightBlue;
        Opacity = .5;

        var forceHandle = Handle;
        BeginInvoke(() => ShowDialog());
    }
}
IVSoftware
  • 5,732
  • 2
  • 12
  • 23
  • To make it easier to try, you can [clone](https://github.com/IVSoftware/wait-form.git) the code I used to test my answer. – IVSoftware Jan 05 '23 at 23:37