Заставка дождавшись, пока поток не завершит


У меня все еще есть проблема с заставкой. Я не хочу использовать это свойство SC.TopMost=true.

Теперь мой сценарий приложения выглядит следующим образом:

В прогерах.cs:

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

В классе SplashScreen:

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++;
    }
}

То, что мне нужно, - это что-то в классе заставки, которое ждет завершения потока.

Для получения более подробной информации, пожалуйста, скажите мне, что я должен вам сказать.
5 19

5 ответов:

Следовать через 2 потока немного запутанно, но я собираюсь сделать удар и сказать это...

Я не совсем понимаю ваш дизайн здесь, но если проблема в том, что при запуске второго приложения форма заставки становится белой... Скорее всего, это связано с тем, что splash screen занят выполнением всего этого кода в GetFromServer(). Настолько занят, что у него нет времени перекрашивать себя.

Чтобы исправить эту проблему, я бы предложил вам использовать BackGroundWorker компонент для выполнения метода GetFromServer. Это позволит запустить этот метод в отдельном потоке и оставить поток формы свободным для перерисовки себя.

Тот же вопрос, тот же ответ:

Платформа .NET framework имеет отличную встроенную поддержку заставок. Запустите новый проект WF, Project + Add Reference, выберите Microsoft.Визуальная основа. Добавьте новую форму, назовите ее frmSplash. открыть проект.cs и сделайте так, чтобы это выглядело следующим образом:

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();
    }
  }
}

Вы вступили на опасную территорию, создав пользовательский интерфейс до вызова приложения.Бежать(). Приложение.Run-это, по сути, насос сообщений вашей программы. Отображая пользовательский интерфейс перед запуском насоса сообщений приложения, вы делаете типичное взаимодействие пользовательского интерфейса практически невозможным на преждевременном пользовательском интерфейсе. Для экрана-заставки это может показаться неуместным, но это будет иметь значение, если (например) есть запрос, чтобы заставить экран-заставку исчезнуть, если он нажат, или вы хотите использовать Фоновый рабочий.

Их можно обойти, создав сообщение pump на экране заставки (сделав его модальным с помощью вызова ShowDialog () вместо Show ()), но это лечение симптома, когда лечение проблемы действительно не так сложно.

Я бы настоятельно рекомендовал ответ нобугза в этом случае. Фреймворк обеспечивает необходимую поддержку. В то время как функции в Microsoft.Пространство имен VisualBasic не всегда доступно для программистов C#, они могут быть настоящий спаситель времени и жизни для таких случаев, как этот.

Удачи!

Вы действительно должны дать более подробную информацию о вашей проблеме. Я могу быть совершенно неправ, но я собираюсь сделать выстрел в темноте. Из того, что я представляю, происходит, и вы хотите, вы хотите, чтобы экран-заставка показывал, выполнял некоторую обработку в другом потоке, а затем экран-заставка исчезал, когда заканчивал.

Чтобы сделать это, вы собираетесь хотите, чтобы переместить GetFromServer() вызов BackgroundWorker. Затем переместите

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

Код для обработчика событий BackgroundWorker_RunWorkerCompleted.

чтобы использовать BackgroundWorker:

1) инициализировать BackGroundWorker

  BackgroundWorker myWorker = new BackgroundWorker();

2) добавить обработчики событий

  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) Добавьте код в обработчики событий. 4) вызовите myWorker.RunWorkerAsync(), чтобы начать работу.

В качестве отдельного замечания, вы, кажется, ничего не делаете с ArrayList, который вы передаете конструктору заставки. Это специально?

К сожалению, у меня пока недостаточно репутации, чтобы комментировать чей-то ответ. : (Это должно быть ответом на комментарий полковника Паникса на ответ Ганса Пассанта .

Его проблема заключалась в том, что MessageBox, показанный из new FormMain(args), будет показан за заставкой. Ключ состоит в том, чтобы вызвать MessageBox из потока, в котором работает заставка:
splashScreen.Invoke(new Action(() => {
    MessageBox.Show(splashScreen, "the message");
}));

Где splashScreen - ссылка на объект заставки, который был создан в OnCreateSplashScreen и, очевидно, должен быть передан в новый объект Form1.