views:

793

answers:

2

I got to load some data out of a db4o database which takes 1 or 2 seconds at the startup of my app, the rest has to wait because first of all the data has to be loaded. doing this in an own thread would mean that the rest has to wait for the thread-finishing. I'd like to do a splash screen or something during the data is loaded for what also need an own thread, right? how would you do?

I'm using csharp, .net 3.5 and winforms

+1  A: 

One way, probably better ways though. Create a new dialog form that will be your progress window/splash screen. Throw a bitmap or whatever on it as the only item. Instantiate the dialog from your main program. Override the Load event for the progress form and from there launch the new thread that will do the background processing work for loading up the data. This way you can just call ShowDialog from your main app.

if you use System.ComponentModel.BackgroundWorker then you can easily wire up events for when the thread completes and automaticaly exit the dialog from that event. Control is returned back to the calling application and you're done.

I've done this sort of thing in an application before and it works fine but I'm sure it's a novice approach. Here's sample code from the Load event in the form that launches the background thread (in my case I'm opening and parsing large files):

 private void FileThreadStatusDialog_Load(object sender, EventArgs e)
 {
Cursor = Cursors.WaitCursor;

if (m_OpenMode)
{
 this.Text = "Opening...";
 StatusText.Text = m_FileName;
 FileThread = new BackgroundWorker();
 FileThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FileThread_RunWorkerCompleted);
 FileThread.DoWork += new DoWorkEventHandler(FileOpenThread_DoWork);
 FileThread.WorkerSupportsCancellation = false;
 FileThread.RunWorkerAsync();
}
else
{
 this.Text = "Saving...";
 StatusText.Text = m_FileName;
 FileThread = new BackgroundWorker();
 FileThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FileThread_RunWorkerCompleted);
 FileThread.DoWork += new DoWorkEventHandler(FileSaveThread_DoWork);
 FileThread.WorkerSupportsCancellation = false;
 FileThread.RunWorkerAsync();
}

}

And here's what the work completed method looks like which exist the form:

private void FileThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    FileThread = null;
        DialogResult = DialogResult.OK;
        Close();
}

Here's how I open up the progress dialog from the main dialog:

FileThreadStatusDialog thread = new FileThreadStatusDialog(m_Engine, dlg.FileName, true);
if (thread.ShowDialog(this) == DialogResult.OK)
{
        m_Engine = thread.Engine;
    FillTree();
}
Atoms
+2  A: 

Showing a splash screen at startup is easy to do. In your application's Main() method (in Program.cs), put something like this before the Application.Run(...) line:

SplashForm splashy = new SplashForm();
splashy.Show();
Application.Run(new MainForm(splashy));

Modify the code and constructor for your main form so that it looks something like this:

private SplashForm _splashy;
public MainForm(SplashForm splashy)
{
    _splashy = splashy;
    InitializeComponent();
}

Then at the end of your MainForm's Load event (which presumably contains the database code), put this code:

_splashy.Close();
_splashy.Dispose();

If you choose to do your database access with a separate Thread or BackgroundWorker, then you don't really need a splash screen so much as you need some sort of progress indicator form that appears while the BackgroundWorker is doing its thing. That would be done differently from my answer here.

MusiGenesis
From a design perspective, there is no need to burden the MainForm with managing the SplashForm. You can use a separate thread or exploit the WinForms.Timer dependency on the MessageLoop.
Henk Holterman
@Henk: or I could just go ahead and "burden" the MainForm with managing the SplashForm, since it's an incredibly simple way to perform an incredibly minor task. Talk about *premature optimization* ...
MusiGenesis