winforms 如何在表单关闭前等待几秒钟?

pxq42qpu  于 2023-10-23  发布在  其他
关注(0)|答案(1)|浏览(123)

也许我的整个逻辑是错误的,但我想,如果用户正在关闭的形式中的一个处理第一更新的richTextBox和删除当前的工作文件夹上,并使一些更多的东西,如等待3秒,然后当完成所有这些任务关闭的形式。
这段代码什么也不做,只是关闭窗体。相反,我希望它等待几秒钟,例如3秒钟,在记录器中显示一条消息,然后在几秒钟后,例如3关闭窗体。
也许我可以使用一些对话框,但我希望如果用户决定关闭表单,那么它将被视为取消。
在大多数应用程序中都有一个对话框,但是对话框是否会在用户决定做什么之前暂停整个表单处理?
表格顶部

private bool isCancelling = false;

然后

private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (isCancelling)
    {
        // Already cancelling, let it continue
        return;
    }

    if (processingFrames)
    {
        // Set the flag to indicate that we are cancelling
        isCancelling = true;

        // Trigger the cancellation
        if (cancellationTokenSource != null)
        {
            cancellationTokenSource.Cancel();
        }

        // Wait for a few seconds before closing the form
        int waitTimeInSeconds = 3; // You can adjust this as needed
        for (int i = waitTimeInSeconds; i > 0; i--)
        {
            logger.Log($"Cancelling in {i} seconds...", Color.Yellow);
            await Task.Delay(1000);
        }

        // Log the cancellation and close the form
        logger.Log("Session Cancelled at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm"), Color.Red);
        logger.Log("", Color.Black);

        DeleteCurrentSession(); // Delete the current session folder

        e.Cancel = false; // Allow the form to close
    }
    else
    {
        // If not processing frames, allow the form to close immediately
        DeleteCurrentSession(); // Delete the current session folder
        e.Cancel = false;
    }
}

另一个问题是在窗体关闭时更新记录器,因为所有内容都被释放了,所以richTextBox1也被释放了,然后我得到一条消息,我可以在form1关闭事件中更新它:
在LogInternal事件中:这条线上

_richTextBox.SelectionStart = _richTextBox.TextLength;

Logger类:
我希望它在关闭窗体之前更新richTextBox。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Test
{
    public class Logger
    {
        private readonly RichTextBox _richTextBox;
        private bool saveToFile; // Added a flag to indicate whether to save to a file
        private string logFilePath = "";

        public Logger(RichTextBox richTextBox, bool saveToFile = false)
        {
            _richTextBox = richTextBox;
            this.saveToFile = saveToFile;

            // Initialize the log file path in the constructor
            InitializeLogFilePath();
        }

        private void InitializeLogFilePath()
        {
            string folderName = "Logs"; // Replace with the desired folder name
            string fileName = "log.txt"; // Replace with the desired file name
            // Set the log file path without creating the directory or file
            logFilePath = Path.Combine(Application.LocalUserAppDataPath, folderName, fileName);
        }

        public void Log(string message, Color textColor)
        {
            if (_richTextBox.InvokeRequired)
            {
                _richTextBox.Invoke((MethodInvoker)delegate
                {
                    LogInternal(message, textColor);
                });
            }
            else
            {
                LogInternal(message, textColor);
            }
        }

        private void LogInternal(string message, Color textColor)
        {
            _richTextBox.SelectionStart = _richTextBox.TextLength;
            _richTextBox.SelectionLength = 0;
            _richTextBox.SelectionColor = textColor;
            _richTextBox.AppendText(message + Environment.NewLine);
            _richTextBox.SelectionColor = _richTextBox.ForeColor;

            // Scroll to the caret (the end)
            _richTextBox.ScrollToCaret();

            if (saveToFile)
            {
                SaveToFile(message); // Save to a file if the flag is set
            }
        }

        private void SaveToFile(string message)
        {
            try
            {
                // Ensure the directory exists, and create it if it doesn't
                string folderName = "Logs"; // Replace with the desired folder name
                string fileName = "log.txt"; // Replace with the desired file name

                // Application.LocalUserAppDataPath
                logFilePath = Path.Combine(Application.LocalUserAppDataPath, folderName, fileName);

                Directory.CreateDirectory(Path.Combine(Application.LocalUserAppDataPath, folderName));

                // Append the message to the log file
                File.AppendAllText(logFilePath, message + Environment.NewLine);
            }
            catch (Exception ex)
            {
                // Handle any exceptions related to file I/O here
                Console.WriteLine("Error saving to log file: " + ex.Message);
            }
        }

        public string LogFilePath()
        {
            return logFilePath;
        }
    }
}
yzuktlbb

yzuktlbb1#

下面是一个表单的工作示例,它在用户单击关闭表单按钮后3秒关闭-除非他们在3秒之前取消。

public class Form1 : Form
{
    private Stopwatch _closingStopwatch = null;
    private System.Windows.Forms.Timer _closingTimer = null;
    private Button _closingCancelButton = null;
    
    protected override void OnLoad(EventArgs e)
    {
        _closingCancelButton = new Button()
        {
            Text = "Cancel Close",
            Enabled = false,
            Width = 160,
        };
        
        _closingCancelButton.Click += (s, a) =>
        {
            _closingTimer.Enabled = false;
            _closingStopwatch = null;
            _closingCancelButton.Enabled = false;
            _closingCancelButton.Text = "Cancel Close";
        };
        
        this.Controls.Add(_closingCancelButton);

        _closingTimer = new System.Windows.Forms.Timer()
        {
            Interval = (int)TimeSpan.FromSeconds(0.1).TotalMilliseconds,
            Enabled = false,
        };
        
        _closingTimer.Tick += (s, a) =>
        {
            var secondsToCloseAt = 3.0;
            if (_closingStopwatch.Elapsed.TotalSeconds >= secondsToCloseAt)
            {
                _closingCancelButton.Enabled = false;
                _closingTimer.Enabled = false;
                this.Close();
            }
            else
            {
                _closingCancelButton.Text = $"Closing in {secondsToCloseAt - _closingStopwatch.Elapsed.TotalSeconds:0.0} seconds.";
            }
        };

        base.OnLoad(e);
    }

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        if (_closingStopwatch == null)
        {
            e.Cancel = true;
            _closingStopwatch = Stopwatch.StartNew();
            _closingCancelButton.Enabled = true;
            _closingTimer.Enabled = true;
        }
        base.OnFormClosing(e);
    }
}

TimerButton之间存在相互作用,以协调3秒的延迟。
关闭前和取消后:

取消前:

以下是Rx版本:

public class Form1 : Form
{
    private Button _closingCancelButton = null;
    private IDisposable _closingSubscription = null;
    
    protected override void OnLoad(EventArgs e)
    {
        _closingCancelButton = new Button()
        {
            Text = "Cancel Close",
            Enabled = false,
            Width = 160,
        };
        
        _closingCancelButton.Click += (s, a) =>
        {
            _closingSubscription.Dispose();
            _closingSubscription = null;
            _closingCancelButton.Enabled = false;
            _closingCancelButton.Text = "Cancel Close";
        };
        
        this.Controls.Add(_closingCancelButton);
        
        base.OnLoad(e);
    }
    
    protected override void OnFormClosing(FormClosingEventArgs e)
    {
    if (_closingSubscription == null)
    {
        e.Cancel = true;
        _closingCancelButton.Enabled = true;
        _closingSubscription =
            Observable
                .Interval(TimeSpan.FromSeconds(0.1))
                .Take(30)
                .Select(x => TimeSpan.FromSeconds(3.0 - x / 10.0))
                .ObserveOn(this)
                .Do(x => _closingCancelButton.Text = $"Closing in {x.TotalSeconds:0.0} seconds.")
                .LastAsync()
                .Subscribe(x => { }, () => this.Close());
        }
        base.OnFormClosing(e);
    }
}

相关问题