线程类'飞溅类型'屏幕上

本文关键字:屏幕 类型 线程 | 更新日期: 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关闭另一个线程调用的表单的最好方法。

线程类'飞溅类型'屏幕上

你的问题似乎不是关于ThreadTask之间的差异,因为你想要的是摆脱"脏"的静态状态。我建议你把它封装到一个类中:

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();