Search code examples
c#winformssplash-screen

splashscreen goes null when calling


I have a splashscreen:

public partial class LoadingScreen : Form
{
    private delegate void CloseDelegate();
    private static LoadingScreen loadingscreen;

    private LoadingScreen()
    {
        InitializeComponent();
    }

    private static void ShowForm()
    {
        loadingscreen = new LoadingScreen();
        Application.Run(loadingscreen);
    }

    public static void ShowLoadingscreen()
    {
        if (loadingscreen != null)
            return;
        System.Threading.Thread thread = new System.Threading.Thread(LoadingScreen.ShowForm);
        thread.IsBackground = true;
        thread.SetApartmentState(System.Threading.ApartmentState.STA);
        thread.Start();
    }

    public static void CloseForm()
    {
        loadingscreen.Invoke(new CloseDelegate(LoadingScreen.CloseFormInternal));
    }

    private static void CloseFormInternal()
    {
        loadingscreen.Close();
        loadingscreen = null;
    }
}

It is called whene the datagrid is busy to refresh (it need some drawing and it takes a while for our hugh data) also whene the user uses the textbox to search something it's triggerd because we need to redraw everything. The code what triggerd the splashscreen:

 private void EditGrid()
    {
        LoadingScreen.ShowLoadingscreen();
        CheckItems();
        EditGridVisibility();
        LoadingScreen.CloseForm();
    } 

when the user types in 3, 4, or 5 characters in the searchbox I get a NullReferenceException on the LoadingScreen.CloseForm(); And it's correct I get a NullRef, because I don't see the form in debugging so there goes something wrong when showing (or closing the last time) but I don't see why.


Solution

  • This error occurs when CloseForm is called before ShowLoadingScreen has had time to spin up it's thread and create loadingScreen.

    It is almost always easier to load/process the data on a background thread and display dialogs on your main UI thread. But if that is not possible, ensure the dialog is displayed before dismissing it or abort its creation.

    A rough solution would be to make the thread global and...

    public static void CloseForm()
    {
        if (loadingscreen == null)
        {
            _thread.Abort();
            return;
        }
        loadingscreen.Invoke(new CloseDelegate(CloseFormInternal));
    }