线程类'飞溅类型'屏幕上
本文关键字:屏幕 类型 线程 | 更新日期: 2023-09-27 18:02:53
给定下面的类,在备用线程上启动启动屏幕:
public partial class SplashForm : Form
{
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();
}
}
使用以下命令调用和关闭
SplashForm.ShowSplash();
SplashForm.CloseSplash();
。
我对TPL并不陌生,当然我们可以在另一个线程上使用简单的东西来显示表单:
Task task = Task.Factory.StartNew(() =>
{
SomeForm someForm = new SomeForm();
someForm.ShowDialog();
};
我的问题是关闭这个SomeForm
当你准备好了。一定有比在SomeForm
类中创建public static
方法更好的方法,比如
private static SomeForm _someForm;
public static void CloseSomeForm()
{
if (_someForm.InvokeRequired)
_someForm.Invoke(new MethodInvoker(CloseSomeForm));
}
我的问题是,使用任务并行库(TPL)上面的SplashForm类做同样的事情的最好方法是什么?具体来说,从UI关闭另一个线程调用的表单的最好方法。
你的问题似乎不是关于Thread
和Task
之间的差异,因为你想要的是摆脱"脏"的静态状态。我建议你把它封装到一个类中:
class SplashController
{
public void Run() {
_someForm = new SomeForm();
someForm.ShowDialog();
}
private SomeForm _someForm;
public void CloseSomeForm()
{
if (_someForm.InvokeRequired)
_someForm.Invoke(new MethodInvoker(CloseSomeForm));
}
}
你可以使用任何你喜欢的线程机制来调用Run。CloseSomeForm不使用线程,所以它是独立的这个问题。
现在可以在任何地方存储对SplashController
实例的引用。在局部变量或静态变量中。后者是有意义的,因为只有一个启动屏幕。
因为静态状态现在被很好地封装了,所以我不认为它被静态保存有任何问题。
你可能不应该这样做
Task task = Task.Factory.StartNew(() =>
{
SomeForm someForm = new SomeForm();
someForm.ShowDialog();
};
,因为它需要一个消息循环出现在创建Form的线程上,这是一个ThreadPool线程。但我还没有测试过。
你可以试试:
public static Task<SplashForm> ShowSplash()
{
var tcs = new TaskCompletionSource<SplashForm>();
// Show the form in a new thread.
_splashThread = new Thread(() =>
{
var splashForm = new SplashForm();
tcs.SetResult(_splashForm);
// Create a new message pump on this thread (started from ShowSplash).
Application.Run(splashForm);
});
_splashThread.IsBackground = true;
_splashThread.Start();
}
允许您从CloseSplash:
中删除静态修饰符。// Close the splash (Loading...) screen.
public void CloseSplash()
{
// Need to call on the thread that launched this splash.
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(CloseSplash));
else
Application.ExitThread();
}
可以这样使用:
var form = await SplashForm.ShowSplash();
form.CloseSplash();