//脚本说明
我正在尝试创建一种定时器,它在启动时使用循环和计数器整数计数,这节省了.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线程关闭表单时,循环已经检查了Counting
是true
,并且即将调用Invoke()
,因此Invoke()
失败。
这实际上比人们想象的更难修复。一个明显的想法是使用锁来防止线程循环在窗体关闭时试图调用,但是如果Form1_FormClosing()在循环试图调用invoke()时被阻塞等待锁,则可能导致死锁。
你考虑过使用计时器来更新标签而不是后台线程吗?这样可以避免这个问题