鉴于下面的课程,要在备用线程上启动启动画面:
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
。必须有比在public static
类中创建SomeForm
方法更好的方法,例如
private static SomeForm _someForm;
public static void CloseSomeForm()
{
if (_someForm.InvokeRequired)
_someForm.Invoke(new MethodInvoker(CloseSomeForm));
}
我的问题是,使用任务并行库(TPL)使用上面的SplashForm类执行相同操作的最佳方法是什么?具体来说,关闭调用表单的最佳方法是来自UI的另一个线程。
答案 0 :(得分:2)
你的问题似乎并不是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
实例的引用。在局部变量中或实际上在静态变量中。后者是有道理的,因为只有一个闪屏。
因为静态状态现在已经很好地封装了,所以我没有看到它被静态保存的任何问题。
答案 1 :(得分:2)
你可能不应该做这样的事情
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中删除static修饰符:
// 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();