You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForm中Timer启动后Tick事件仅在方法结束后触发问题求助

问题根因

你使用的是WinForm原生的System.Windows.Forms.Timer,其Tick事件依赖UI线程的消息循环调度。当前recorrido方法同步运行在UI线程上,全程占用UI线程资源,导致Timer的消息无法被及时分发,只能等整个方法执行完成后才会处理积压的Tick事件。同时原有逻辑还存在缺陷:调用segundero启动Timer后没有等待执行完成,直接进入下一次循环,会覆盖SegundoTerminar等共享变量,就算Timer正常触发也会出现数值混乱。

修复方案

采用异步逻辑改造,不阻塞UI线程,同时等待单步Timer执行完成后再处理下一个批处理任务,代码改造示例如下:

Stopwatch oSW = new Stopwatch();
// 新增TaskCompletionSource用于等待Timer执行完成
TaskCompletionSource<bool> timerTcs;

void segundero()
{
    oSW.Reset();
    oSW.Start();
    timer1.Enabled = true;
    timer1.Start();
}

// 改造为异步方法
async Task recorrido(int i)
{
    int num1;
    int num2;
    int res = 0;
    for(int k =i; k<= i+3; k++)
    {
        if (k < NuProcesos)
        {
            num1 = ListOp1[k];
            num2 = ListOp2[k];
            if (Oper[k] == "+")
            {
                res = num1 + num2;
            }
            else if (Oper[k] == "-")
            {
                res = num1 - num2;
            }
            else if (Oper[k] == "*")
            {
                res = num1 * num2;
            }
            else if (Oper[k] == "/")
            {
                res = num1 / num2;
            }
            else if (Oper[k] == "%")
            {
                res = num1 % num2;
            }
            operacionactual = ListOp1[k].ToString() + Oper[k].ToString() + ListOp2[k] + " = " + res.ToString();
            SegundoMenos = 0;
            SegundoTerminar = LisTime[k];
            SegundoTerminar1 = LisTime[k];
            loteproceso.Rows[0].Cells[0].Value = NombreP[k];
            loteproceso.Rows[0].Cells[1].Value = operacionactual;
            loteproceso.Rows[0].Cells[2].Value = LisTime[k];
            loteproceso.Rows[0].Cells[3].Value = IDNumero[k];
            
            // 初始化等待源
            timerTcs = new TaskCompletionSource<bool>();
            segundero();
            // 等待当前Timer执行完成再进入下一个任务
            await timerTcs.Task;
            
            procesoterminado.Rows.Add(IDNumero[k], operacionactual, nlote);
        }
    }
}

private void timer1_Tick(object sender, EventArgs e)
{
    TimeSpan ts = new TimeSpan(0, 0, 0, 0, (int)oSW.ElapsedMilliseconds);

    SegundoMenos = SegundoMenos + 1;
    SegundoTerminar = SegundoTerminar - 1;
    loteproceso.Rows[0].Cells[4].Value = SegundoTerminar;
    loteproceso.Rows[0].Cells[5].Value = SegundoMenos;
    if (SegundoTerminar==0) 
    {
        oSW.Reset();
        timer1.Enabled = false;
        // 通知等待的任务已完成
        timerTcs.SetResult(true);
    }
}

改造完成后,原来调用recorrido的地方需要改成await recorrido(参数),且调用方法需要标记为async。

内容的提问来源于stack exchange,提问作者CLAUDIO SEBASTIAN ORTEGA RAMIR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 16:57:05