动态更新 UI 时执行线程

本文关键字:执行 线程 UI 更新 动态 | 更新日期: 2023-09-27 18:36:36

我一直在试图解决这个问题。在线程方面,我很困惑。

我试图做的是在函数中延迟 1 次暂停并继续该函数,直到另一个 1 秒暂停并最终完成该函数。

public partial class SplashScreen : Form
{
    public SplashScreen()
    {
        InitializeComponent(); // initalize splash screen
        DatabaseStatus(); // set database connection
        getUserInfo(); // get user information
        showInfo(); // show app information on splash screen
        System.Threading.Thread wa = new System.Threading.Thread(new System.Threading.ThreadStart(checkUser));
        wa.IsBackground = true;
        wa.Start();
    }
    void checkUser()
    { 
        if (RegisteredUser)
        {
            richTextBox1.Text += "Loading user settings...";  // SHOW THIS TEXT AND WAIT 1 SECOND UNTIL NEXT
            System.Threading.Thread.Sleep(1000); 
            if (DATABASE_CONNECTION)
            {
                richTextBox1.Text += "Loging on...";
                // WAIT AGAIN 1 SEC AND CONTINUE///
                LoginCheck login = new LoginCheck(USER_NAME, PASSWORD);
                if (login.LOGIN_SUCESS)
                {
                    richTextBox1.Text += "Sucess!";
                   // SHOW THIS TEXT AND WAIT 1 SEC UNTIL SPLASH SCREEN FADE OUT//
                    //MessageBox.Show(login.HASH);
                    opac.Interval = 12;
                    opac.Start();
                    opac.Tick += new EventHandler(dec);
                }
                else
                {
                    MessageBox.Show(login.HASH);
                }
            }
        }
        else
        {
            richTextBox1.Text += "Not user profile found...";
            // ask user to register
        }
    }
}

我放置评论的地方是我希望线程暂停并继续的地方......

有人有任何意见吗?

谢谢

动态更新 UI 时执行线程

首先,您必须知道何时使用 WinForms(以及 WPF/Silverlight...对吧?您不能也不应该从任何其他线程操作 UI 元素,但创建窗体/控件的原始线程除外。

如果需要执行异步工作,则需要使用 InvokeBeginInvoke将 UI 工作转换回窗体或控件的线程。此外,请考虑使用委托(MethodInvoker很方便),而不是创建自己的线程。

此外,您需要在 Load 事件期间或之后启动异步工作,否则您的逻辑将在表单显示之前开始执行(请参阅下面的示例)。

以你的例子为例,把它放进我自己的简化样本中。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        RegisteredUser = true;
        DATABASE_CONNECTION = true;

    }
    private void UpdateStatus(string message)
    {
        BeginInvoke(new MethodInvoker(() => richTextBox1.Text += message));
    }
    private void CheckUser()
    {
        if (RegisteredUser)
        {
            UpdateStatus("Loading user settings..."); // SHOW THIS TEXT AND WAIT 1 SECOND UNTIL NEXT
            System.Threading.Thread.Sleep(1000);
            if (DATABASE_CONNECTION)
            {
                UpdateStatus("Logging on...");
                //// WAIT AGAIN 1 SEC AND CONTINUE///
                //LoginCheck login = new LoginCheck(USER_NAME, PASSWORD);
                if (true)//login.LOGIN_SUCESS)
                {
                    UpdateStatus("Success!");
                    // SHOW THIS TEXT AND WAIT 1 SEC UNTIL SPLASH SCREEN FADE OUT//
                    //MessageBox.Show(login.HASH);
                    //opac.Interval = 12;
                    //opac.Start();
                    //opac.Tick += new EventHandler(dec);
                }
                else
                {
                    //MessageBox.Show(login.HASH);
                }
            }
        }
        else
        {
            UpdateStatus("No user profile found.");
            // ask user to register
        }
    }
    protected bool DATABASE_CONNECTION { get; set; }
    protected bool RegisteredUser { get; set; }
    private void Form1_Load(object sender, EventArgs e)
    {
        var invoker = new MethodInvoker(CheckUser);
        invoker.BeginInvoke(null, null);
    }
}

如您所见,我使用诸如UpdateStatus之类的方法来为我处理UI,确保其在UI线程上完成。您可以使用任意数量的类似方法在 UI 中执行其他操作,例如触发窗体的淡入淡出或其他操作。

您甚至不应该在 UI 线程之外显示消息框;通过类似的方法安全地调用这些消息框(此外,对于调试,只需Debug.WriteLine将消息写入调试器,而不是弹出整个消息框)。

我建议您在单独的后台工作线程中执行所有操作,并在 UI 中更新状态。 这使得 UI 更快,您的应用程序更可靠。

http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

你需要使用 Invoke() 看到这个

public partial class SplashScreen : Form
{      
    bool DATABASE_CONNECTION;
    bool RegisteredUser; // if user has been registered
    string USER_NAME;
    string PASSWORD;
    double LIN_x = 0.01;
    DialogResult result;
    custom con = new custom();
    Timer opac = new Timer();
    public SplashScreen()
    {
        InitializeComponent(); // initalize splash screen
        DatabaseStatus(); // set database connection
        getUserInfo(); // get user information
        showInfo(); // show app information on splash screen
    }
    private void UpdateStatus(string message)
    {
        BeginInvoke(new MethodInvoker(() => richTextBox1.Text += message + Environment.NewLine));
    }
    void checkUser()
    {
        UpdateStatus("Loading user settings..."); 
        if (RegisteredUser)
        {
            UpdateStatus("User " + USER_NAME + " found." );
            if (DATABASE_CONNECTION)
            {
                UpdateStatus("Logging on..."); 
                LoginCheck login = new LoginCheck(USER_NAME, PASSWORD);
                if (login.LOGIN_SUCESS)
                {
                    UpdateStatus("Success! Loading " + con.AppTitle() + "...please wait");
                    //UpdateStatus(login.HASH); return hash string from web site
                    fadeSplash(); // begin fade out of form
                }
                else
                {
                    UpdateStatus("There was an error logging in."); 
                }
            }
            else
            {
                UpdateStatus("No database connection found."); 
            }
        }
        else
        {
            UpdateStatus("No user found"); 
            Reg(); // Registration form
        }
    }
    private void fadeSplash()
    {
        opac.Interval = 12;
        opac.Tick += new EventHandler(dec);
        opac.Start();
    }
    private void dec(object sender, EventArgs e)
    {
        this.Opacity -= LIN_x;
        if (this.Opacity < 0.04)
        {
            opac.Stop();
            this.Hide();
            main open = new main(); // start application
            open.Show();
        }
    }
}
下面是在方法

调用期间淡入淡出方法不触发

的代码