我仍然遇到启动画面问题。我不想使用属性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++;
}
}
我想要的是启动画面类中等待线程完成的内容。
有关详细信息,请告诉我需要告诉您的内容。
答案 0 :(得分:82)
同样的问题,同样的答案:
.NET框架对启动画面具有出色的内置支持。启动一个新的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();
}
}
}
答案 1 :(得分:3)
您在调用Application.Run()之前创建了UI,从而进入了危险区域。 Application.Run本质上是您程序的消息泵。通过在启动应用程序的消息泵之前显示UI,您可以在过早的UI上实现典型的UI交互。对于启动画面,这看起来似乎不相关,但是如果(例如)有一个请求使得启动画面在单击时消失,或者您想要使用BackgroundWorker,则会很重要。
可以通过在启动画面中创建消息泵来解决这些问题(通过调用ShowDialog()而不是Show()使其成为模态,但是在处理问题时,这是否正在处理症状困难的。
在这种情况下,我强烈鼓励nobugz's answer。该框架提供您所需的支持。虽然Microsoft.VisualBasic命名空间中的功能对于C#程序员来说并不总是非常容易被发现,但对于这样的情况,它们可以成为真正的节省时间和救星。
祝你好运!答案 2 :(得分:1)
跨越2个线程有点令人困惑,但我会采取刺戳并说出来......
我在这里并不完全理解您的设计,但如果问题是当您启动第二个应用程序时,启动屏幕形式变为白色...这很可能是因为启动画面正在忙于执行所有这些GetFromServer()中的代码。如此忙碌以至于没有时间重新粉刷自己。
要解决此问题,我建议您使用BackGroundWorker component执行GetFromServer方法。这将在一个单独的线程中运行该方法,并让表单的线程自由重新绘制自己。
答案 3 :(得分:1)
你真的应该提供有关你的问题的更多细节。我可能完全错了,但我会在黑暗中拍摄。从我想象中发生的和你想要的,你想要启动闪屏,在另一个线程中进行一些处理,然后在完成时闪屏就消失了。
为此,您需要将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
做任何事情。这是为了吗?
答案 4 :(得分:1)
不幸的是,我没有足够的声誉对某人的答案发表评论。 :(这是Colonel Panics comment on Hans Passants answer的答案。
他的问题是,MessageBox
显示的new FormMain(args)
将显示在启动画面后面。关键是从启动屏幕运行的线程调用MessageBox:
splashScreen.Invoke(new Action(() => {
MessageBox.Show(splashScreen, "the message");
}));
splashScreen
是对OnCreateSplashScreen
中创建的启动画面对象的引用,显然必须提供给新的Form1
对象。