You need to enable JavaScript to run this app. C#开发的自动点击器关闭后仍驻留后台无法正常退出问题求助
优惠活动
大模型
产品
解决方案
定价
更多

C#开发的自动点击器关闭后仍驻留后台无法正常退出问题求助

问题原因

你启动的Thread默认是前台线程,且两个执行逻辑(AutoClick、backgroundWorker1_DoWork)都是无限while(true)循环,没有终止逻辑。前台线程不会随主UI线程退出而终止,所以窗体关闭后线程仍在后台运行,导致进程残留。

解决方案

按以下步骤修改代码即可:

1. 新增全局退出标识

在Form1类中新增退出标记:

public bool IsExit = false;

2. 配置线程属性并开启BackgroundWorker取消支持

修改Form_Load方法,将自定义线程设为后台线程,同时开启BackgroundWorker的取消功能:

private void Form1_Load(object sender, EventArgs e)
{
    CheckForIllegalCrossThreadCalls = false;
    Thread AC = new Thread(AutoClick);
    // 设为后台线程,主进程退出时会自动终止该线程
    AC.IsBackground = true;
    // 开启BackgroundWorker的取消支持,也可以在设计器属性面板中设置
    backgroundWorker1.WorkerSupportsCancellation = true;
    backgroundWorker1.RunWorkerAsync();
    AC.Start();
}

3. 修改循环终止条件

把两个无限循环的终止条件替换为判断退出标识:

AutoClick方法修改

private void AutoClick()
{
    // 替换原来的while(true)
    while (!IsExit)
    {
        if(Click == true)
        {
            mouse_event(dwFlags: LEFTUP, dx: 0, dy: 0, cButtons: 0, dwExtraInfo: 0);
            Thread.Sleep(1);
            mouse_event(dwFlags: LEFTDOWN, dx: 0, dy: 0, cButtons: 0, dwExtraInfo: 0);
            Thread.Sleep(intervals);
        }
        Thread.Sleep(2);
    }
}

backgroundWorker1_DoWork方法修改

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // 替换原来的while(true)
    while (!backgroundWorker1.CancellationPending && !IsExit)
    {
        if (checkBox1.Checked)
        {
            if(GetAsyncKeyState(Keys.Down)< 0)
            {
                Click = false;
            }
            else if(GetAsyncKeyState(Keys.Up)< 0)
            {
                Click = true;
            }
            
            Thread.Sleep(1);
        }
    }
    e.Cancel = true;
}

4. 统一退出逻辑,同时处理窗体关闭事件

新增通用退出方法,同时绑定退出按钮和窗体右上角关闭按钮的事件:

private void button2_Click(object sender, EventArgs e)
{
    ExitProcess();
}

// 需要在设计器中给Form1绑定FormClosing事件
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    ExitProcess();
}

private void ExitProcess()
{
    // 触发退出标识,终止线程循环
    IsExit = true;
    // 取消BackgroundWorker任务
    if (backgroundWorker1.IsBusy)
    {
        backgroundWorker1.CancelAsync();
    }
    // 等待线程资源释放,最多等待1秒避免界面卡住
    Thread.Sleep(1000);
    Application.Exit();
    // 如果还有进程残留,可加下面的代码强制终止所有线程
    // Environment.Exit(0);
}

补充说明

代码中CheckForIllegalCrossThreadCalls = false;是不安全的跨线程访问处理方式,正式项目建议用委托实现跨线程控件访问,小工具临时使用可以保留。另外mouse_event是已过时的API,后续优化可以替换为SendInput。

内容的提问来源于stack exchange,提问作者Gigel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 12:54:05