UI线程被阻塞
我是新来的C#,我工作了软件启动时运行启动屏幕上。我在启动屏幕类中检查数据库的功能。我正在使用线程调用函数
sc = new splashScreen();
checkDLLThread = new Thread(new ThreadStart(sc.checkDLLS).BeginInvoke);
checkDLLThread.Start();
while (checkDLLThread.IsAlive)
{
Thread.Sleep(200);
}
问题是UI被阻塞,直到线程处于活动状态。并在最后它给我数据库连接状态消息。 这是我的代码。我已经使用checkDLLThread.join(),但它也不起作用。
splashscreen仅仅是一个图像,当您的应用程序加载时可以“充满”用户。使用app_load方法在启动时执行代码:
像这样:(在App.xaml中和app.xaml.cs)
<Application /some references to stuff/ Startup="Application_Startup" >
private void Application_Startup(object sender, StartupEventArgs e)
{
// your startupcode
}
而且,我觉得BackGroundworker类是这样的事情更好,如果你不想打扰用户界面。
我正在使用VS 2005,在那里我可以找到这个东西 – greatmajestics 2012-08-04 10:38:05
我假设你正在使用WPF。你使用Windows窗体吗? – AmazingDreams 2012-08-04 10:38:55
我认为将代码放入Application_Startup也会阻止(为什么不呢?想不出任何理由)。 – usr 2012-08-04 10:39:27
解除屏蔽UI线程需要从您的事件处理程序返回。除此之外别无选择。这里是一些伪代码:
OnStartup:
Start new Thread
Disable UI
Show Splash Sceen
Return!
Thread:
Check Database
if (not ok)
Show Message box
Exit Application
else
Enable UI
Remove Splash Screen
诀窍是让线程显示消息,等一旦完成。不要等待线程,让线程自己做。
您的线程可能需要使用Invoke函数来访问UI。如果你想在后台线程上执行异步工作,你可能不会阅读这些内容,因为没有办法绕过它。
下面的代码在单独的线程上启动一个“启动画面”,而您的应用程序(在我的示例中,它被称为MainForm())加载或初始化。首先在你的“main()”方法中(在你的program.cs文件中,除非你重命名了它),你应该显示你的启动画面。这将是一个WinForm或WPF表单,您希望在启动时向用户显示。这是主要推出()如下:
[STAThread]
static void Main()
{
// Splash screen, which is terminated in MainForm.
SplashForm.ShowSplash();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Run UserCost.
Application.Run(new MainForm());
}
在你的闪屏的代码,你需要像下面这样:
public partial class SplashForm : Form
{
// Thredding.
private static Thread _splashThread;
private static SplashForm _splashForm;
public SplashForm()
{
InitializeComponent();
}
// Show the Splash Screen (Loading...)
public static void ShowSplash()
{
if (_splashThread == null)
{
// show the form in a new thread
_splashThread = new Thread(new ThreadStart(DoShowSplash));
_splashThread.IsBackground = true;
_splashThread.Start();
}
}
// Called by the thread
private static void DoShowSplash()
{
if (_splashForm == null)
_splashForm = new SplashForm();
// create a new message pump on this thread (started from ShowSplash)
Application.Run(_splashForm);
}
// Close the splash (Loading...) screen
public static void CloseSplash()
{
// Need to call on the thread that launched this splash
if (_splashForm.InvokeRequired)
_splashForm.Invoke(new MethodInvoker(CloseSplash));
else
Application.ExitThread();
}
}
这将启动飞溅的形式在一个单独的后台线程允许你继续同时呈现您的主应用程序。要显示关于加载的消息,您必须从主UI线程获取信息,或者以纯粹的审美性质工作。为了完成并关闭闪屏下来的时候你的应用程序已被初始化你把默认的构造函数中以下(你可以重载的构造函数,如果你想):
上面的代码应该是比较容易跟随。
我希望这会有所帮助。
你的方法很好,但你应该同时运行。使用static fields
可以轻松完成这项工作。相反的:
while (checkDLLThread.IsAlive)
{
Thread.Sleep(200);
}
你应该:
- 显示启动
Form
- 设置上开始被隐藏的形式,即设置
Opacity
到0
- 检查不断在变
SplashForm
当您的表单完全初始化时 - Set
Opacity
当线程完成时返回1
。即变量变化
i.e.:
public Form1(){
InitializeComponent();
Opacity = 0;
while(sc.IsComplete){}
Opacity = 1;
}
和你SplashForm
里面,你应该有像:
internal static bool IsComplete;
internal static void CheckDLLS()
{
//after doing some stuff
IsComplete = true;
}
你为什么不只是删除的睡眠?这是什么阻止用户界面。 – usr 2012-08-04 10:32:38
我已经尝试通过删除睡眠,循环然后阻止用户界面 – greatmajestics 2012-08-04 10:37:32
好吧,当然也删除循环;-)解除屏蔽UI线程需要从您的事件处理程序返回。 – usr 2012-08-04 10:38:44