VS 2022 C# 窗体:系统无效操作异常:"在创建窗口句柄之前,无法在控件上调用 Invoke 或 BeginInvoke。



//脚本说明

我正在尝试创建一种定时器,它在启动时使用循环和计数器整数计数,这节省了.txt文件的秒数,并在程序停止时停止。

因为我使用一个while循环计数,我必须在一个单独的线程中这样做,以避免耽误UI更新,因此在单独的线程中计数,然后调用文本到UI函数

脚本将在底部,但我认为我将包括这个解释,以便更容易理解。

//问题

这一切都很好,它更新文本标签,以显示经过的秒数很好,然而,当试图关闭应用程序时,它抛出一个异常,我试图通过将bool检查放在何时应该计数,不应该在while循环内计数来修复,而不是在true为true时运行while循环。我在脚本开始定义bool时激活它,并在Form1_FormClosing事件上禁用它,但它仍然抛出以下异常:

System.InvalidOperationException: 'Invoke or BeginInvoke cannot be called on a control until the window handle has been created.'

//My Script

using System;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Reflection.Emit;
namespace PC_Timer
{
public partial class Form1 : Form
{
private bool Counting = true;
private int count = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (File.Exists("count.txt"))
{
string text = File.ReadAllText("count.txt");
count = int.Parse(text);
label1.Text = count.ToString() + " Seconds";
}
else
{
File.WriteAllText("count.txt", "0");
}
new Thread(Loop).Start();
}
private void Loop()
{
while (Counting)
{
count++;
label1.Invoke((MethodInvoker)delegate {
label1.Text = count.ToString() + " Seconds";
});
Thread.Sleep(1000);
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Counting = false;
File.WriteAllText("count.txt", count.ToString());
}
}
}

//备注

也许有比在while循环中做这个更好的方法,因为它们效率很低,但是这应该是一个简单的程序,用于单独使用,这就是为什么我用while循环来做它,因为它是我最舒服的。

我还试图检查IsHandleCreated是否为真,这确实有效,但我不认为它处理了异常,因为我无法发布它,因为一个或多个错误,Visual Studio无法确定原因。

无论如何,我应该做什么不同的调用函数不卡住时退出程序?

这是一个典型的竞争条件。当主UI线程关闭表单时,循环已经检查了Countingtrue,并且即将调用Invoke(),因此Invoke()失败。

这实际上比人们想象的更难修复。一个明显的想法是使用锁来防止线程循环在窗体关闭时试图调用,但是如果Form1_FormClosing()在循环试图调用invoke()时被阻塞等待锁,则可能导致死锁。

你考虑过使用计时器来更新标签而不是后台线程吗?这样可以避免这个问题

最新更新