Заставка ожидания до завершения потока - PullRequest
19 голосов
/ 25 декабря 2008

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

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

в progeram.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 ]

82 голосов
/ 26 декабря 2008

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

.NET Framework имеет отличную встроенную поддержку для заставок. Запустите новый проект WF, Project + Add Reference, выберите Microsoft.VisualBasic. Добавьте новую форму, назовите ее frmSplash. Откройте Project.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();
    }
  }
}
3 голосов
/ 26 декабря 2008

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

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

Я бы настоятельно рекомендовал ответу nobugz в этом случае. Каркас предоставляет необходимую вам поддержку. Хотя функции в пространстве имен Microsoft.VisualBasic не всегда могут быть обнаружены программистами на C #, в таких случаях они могут быть реальными и спасительными.

Удачи!

1 голос
/ 26 ноября 2013

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

Его проблема заключалась в том, что MessageBox, показанный из new FormMain(args), будет отображаться за заставкой. Ключ заключается в том, чтобы вызвать MessageBox из потока, в котором работает заставка:

splashScreen.Invoke(new Action(() => {
    MessageBox.Show(splashScreen, "the message");
}));

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

1 голос
/ 25 декабря 2008

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

Для этого вам нужно переместить вызов 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, который вы передаете конструктору заставки. Это предназначено?

1 голос
/ 25 декабря 2008

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...