views:

3574

answers:

4

Dear All,

I still have a problem with the splash screen. I don't want to use the property SC.TopMost=true.

Now my application scenario is as follows:

in progeram.cs:

    [STAThread]
    static void Main()
    {
        new SplashScreen(_tempAL);// where _tempAL is an arrayList
        Application.Run(new Form1(_tempAL));
    }

in SplashScreen class:

   public SplashScreen(ArrayList _Data)
   {
        DisplaySplash()
   } 
   private void DisplaySplash()
    {
        this.Show();
        this.TopMost = true;
        this.CenterToScreen();
        this.SetTopLevel(true);

        _allServerNarrators = new string[10];
        for (int i = 0; i < _allServerNarrators.Length; i++)
            _allServerNarrators[i] = null;

        GetFromServer();

        this.Hide();
        _serverData = new ArrayList();
        _thisData.Add(_allServerNarrators);
        _thisData.Add(_serverNarrators);

    }
    private void GetFromServer()
    {
        _serverNarrators = new ArrayList();
        string _file = "Suras.serverNar";

        if (!Directory.Exists("c:\\ASGAQuraan"))
            Directory.CreateDirectory("c:\\ASGAQuraan");

        while (counter < 4 && _serverFiles == null)
        {
            if (Download("c:\\ASGAQuraan", _ftpServerIP, _file))
            {
                StreamReader _strReader = new StreamReader
                             ("c:\\ASGAQuraan\\"+_file,System.Text.Encoding.Default);
                string _line = _strReader.ReadLine();
                string _word;

                while (true)
                {
                    while (_line != null)
                    {
                        _word = _line.Substring(0, _line.IndexOf("*"));
                        int _narId = Convert.ToInt32(_word);
                        _line = _line.Substring(2);
                        int k = 0;
                        _serverNarratorNode = new ArrayList();
                        while (true)
                        {
                            int ind = _line.IndexOf("*");
                            if (ind > 0 && ind < _line.Length)
                            {
                                string str = _line.Substring(0, (ind));
                                if (k == 0)
                                {
                                    _allServerNarrators[_narId] = str;
                                    _serverNarratorNode.Add(str);
                                }
                                else
                                {
                                    _serverNarratorNode.Add(str);
                                }
                                _line = _line.Substring(ind + 1);
                                k++;
                            }
                            else
                            {
                                _line = null;
                                break;
                            }
                        }
                        _serverNarrators.Add(_serverNarratorNode);
                        _serverFiles = "added";
                    }
                    _line = _strReader.ReadLine();
                    if (_line == null)
                    {
                        break;
                    }
                }
            }
            else
                counter++;
        }
    }

What I want is something in the splash screen class which waits until the thread finishes.

For more details, please tell me what I need to tell you.

A: 

Following across 2 threads is a bit confusing, but I'm going to take a stab and say this...

I don't fully understand your design here, but if the issue is that when you launch a second application the splash screen form turns white... It's most likely due to the fact that splash screen is busy executing all of that code in GetFromServer(). So busy that it has no time to re-paint itself.

To remedy this problem I would suggest that you use the BackGroundWorker component to execute the GetFromServer method. This will run that method in a separate thread and leave the form's thread free to re-paint itself.

+1  A: 

You really should give more details about your problem. I could be completely wrong, but I'm going to take a shot in the dark. From what I'm imagining is going on and you want, you want the splash screen to show, do some processing in another thread, then the splash screen to go away when finished.

To do this, you're going to want to move the GetFromServer() call to a BackgroundWorker. Then move the

    this.Hide();
    _serverData = new ArrayList();
    _thisData.Add(_allServerNarrators);
    _thisData.Add(_serverNarrators);

code to the BackgroundWorker_RunWorkerCompleted event handler.

To use the BackgroundWorker:

1) Initialize the BackGroundWorker

  BackgroundWorker myWorker = new BackgroundWorker();

2) Add event handlers

  myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
  //put the work you want done in this one

  myWorker.RunWorkerCompleted += 
      new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
  //this gets fired when the work is finished

3) Add code to the event handlers.

4) Call myWorker.RunWorkerAsync() to start working.

As a separate note, you don't seem to be doing anything with the ArrayList that you're passing to the splash screen's constructor. Is this intended?

lc
+18  A: 

Same question, same answer:

The .NET framework has excellent built-in support for splash screens. Start a new WF project, Project + Add Reference, select Microsoft.VisualBasic. Add a new form, call it frmSplash. Open Project.cs and make it look like this:

using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;

namespace WindowsFormsApplication1 {
  static class Program {
    [STAThread]
    static void Main(string[] args) {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      new MyApp().Run(args);
    }
  }
  class MyApp : WindowsFormsApplicationBase {
    protected override void OnCreateSplashScreen() {
      this.SplashScreen = new frmSplash();
    }
    protected override void OnCreateMainForm() {
      // Do your time consuming stuff here...
      //...
      System.Threading.Thread.Sleep(3000);
      // Then create the main form, the splash screen will close automatically
      this.MainForm = new Form1();
    }
  }
}
Hans Passant
What if you wanted to pass args to Form1 ? I was able to do this using a static class to store the value, but I was wondering if you had a simpler way.
KClough
Just use this.MainForm = new Form1(arguments);
Hans Passant
+3  A: 

You've entered dangerous territory by creating UI prior to your call to Application.Run(). Application.Run is essentially your program's message pump. By displaying the UI before you start the application's message pump, you make typical UI interaction effectively impossible on the premature UI. For a splash screen this may not seem relevant, but it will matter if (e.g.) there's a request to make the splash screen disappear if it's clicked on, or you want to use a BackgroundWorker.

These can be worked around by creating a message pump in your splash screen (by making it modal via a call to ShowDialog() instead of Show()), but that's treating the symptom when treating the problem really isn't that difficult.

I'd strongly encourage nobugz's answer in this case. The framework provides the support you need. While features in the Microsoft.VisualBasic namespace aren't always very discoverable to C# programmers, they can be a real timesaver and lifesaver for cases like this.

Good luck!

Greg D