Заставка ожидания до завершения потока
У меня все еще есть проблема с заставкой. Я не хочу использовать собственность 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 ответов
Отслеживание двух потоков немного сбивает с толку, но я собираюсь сделать удар и сказать это...
Я не до конца понимаю ваш дизайн, но если проблема в том, что при запуске второго приложения форма заставки становится белой... Это, скорее всего, связано с тем, что заставка занята выполнением всего этого кода в GetFromServer(). Настолько занят, что у него нет времени перекрашивать себя.
Чтобы устранить эту проблему, я бы предложил использовать компонент BackGroundWorker для выполнения метода GetFromServer. Это запустит этот метод в отдельном потоке и оставит поток формы свободным для перерисовки.
Тот же вопрос, тот же ответ:
.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();
}
}
}
Вы вошли в опасную территорию, создав пользовательский интерфейс до вызова Application.Run(). Application.Run - это, по сути, насос сообщений вашей программы. Отображая пользовательский интерфейс перед тем, как запустить модуль обработки сообщений приложения, вы фактически делаете невозможным типичное взаимодействие с пользовательским интерфейсом на преждевременном пользовательском интерфейсе. Для заставки это может показаться неуместным, но будет иметь значение, если (например) есть запрос на удаление заставки, если на нее щелкнули, или вы хотите использовать BackgroundWorker.
Это можно обойти, создав насос сообщений на заставке (сделав его модальным с помощью вызова ShowDialog() вместо Show()), но это лечит симптом, когда лечение проблемы действительно не так сложно.
Я бы настоятельно рекомендовал ответ Нобугз в этом случае. Каркас предоставляет необходимую поддержку. Хотя функции в пространстве имен Microsoft.VisualBasic не всегда могут быть обнаружены программистами на C#, они могут быть реальным способом экономии времени и жизни в таких случаях.
Удачи!
К сожалению, у меня недостаточно репутации, чтобы комментировать ответы.:(Это должно быть ответом на комментарий полковника Паники на ответ Ганса Пассанта.
Его проблема заключалась в том, что MessageBox
показано из new FormMain(args)
будет отображаться за заставкой. Ключ заключается в том, чтобы вызвать MessageBox из потока, в котором работает заставка:
splashScreen.Invoke(new Action(() => {
MessageBox.Show(splashScreen, "the message");
}));
куда splashScreen
является ссылкой на объект заставки, который был создан в OnCreateSplashScreen
и, очевидно, должен быть отдан новому Form1
объект.
Вы действительно должны дать более подробную информацию о вашей проблеме. Я могу быть совершенно неправ, но я собираюсь сделать снимок в темноте. Исходя из того, что я представляю себе, вы хотите, чтобы показывался заставка, выполнялась некоторая обработка в другом потоке, а затем заставка исчезала по окончании.
Для этого вам понадобится переместить 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
что вы передаете конструктор заставки. Это предназначено?