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

如何在Timer.periodic执行后添加延迟以避免数据丢失?

解决串行消息发送冲突问题

你的核心问题是多个发送请求并发/连续执行,导致接收端无法及时处理而丢数据。单纯给Timer加延迟无法从根本上解决问题(比如用户连续点击按钮时,延迟依然会导致冲突),最可靠的方案是给所有发送请求做串行队列处理,保证同一时间只有一个消息在发送,前一个发送完成后再处理下一个。

实现步骤

  1. 维护一个消息队列,存储待发送的消息;
  2. 用一个标记变量记录当前是否正在发送,避免并发执行;
  3. 统一通过入队方法触发发送,由队列处理器串行处理所有消息。

修改后的完整代码

import 'dart:collection';
import 'dart:async';
import 'package:flutter/material.dart';

class YourPage extends StatefulWidget {
  const YourPage({super.key});

  @override
  State<YourPage> createState() => _YourPageState();
}

class _YourPageState extends State<YourPage> {
  Timer? timer;
  // 消息队列:存储所有待发送的消息
  final Queue<String> _messageQueue = Queue<String>();
  // 标记当前是否正在发送消息
  bool _isSending = false;

  @override
  void initState() {
    super.initState();
    // Timer触发的Alive消息改为入队
    timer = Timer.periodic(Duration(seconds: 5), (Timer t) => 
      enqueueMessage('Alive'));
  }

  @override
  void dispose() {
    timer?.cancel();
    super.dispose();
  }

  // 将消息加入队列,并触发队列处理
  void enqueueMessage(String message) {
    _messageQueue.add(message);
    _processMessageQueue();
  }

  // 串行处理消息队列
  Future<void> _processMessageQueue() async {
    // 如果正在发送或队列为空,直接返回
    if (_isSending || _messageQueue.isEmpty) return;

    _isSending = true;
    try {
      // 取出队列头部的消息
      final message = _messageQueue.removeFirst();
      // 执行实际的发送逻辑(替换成你原来的_sendmessage实现)
      await _sendMessageToDevice(message);
      // 当前消息发送完成后,继续处理下一个
      _processMessageQueue();
    } finally {
      // 无论发送成功/失败,都标记发送状态结束
      _isSending = false;
    }
  }

  // 实际的设备发送逻辑(原_sendmessage的核心代码)
  Future<void> _sendMessageToDevice(String message) async {
    // 这里替换成你的发送实现,比如蓝牙、网络通信
    // 示例:等待发送完成(模拟耗时操作)
    await Future.delayed(Duration(milliseconds: 500));
    print('已发送:$message');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('消息发送示例')),
      body: Center(
        child: ElevatedButton(
          // 按钮点击的消息也通过入队处理
          onPressed: () => enqueueMessage('按钮触发的自定义数据'),
          child: Text('发送自定义数据'),
        ),
      ),
    );
  }
}

方案优势

  • 彻底避免冲突:所有消息按顺序串行发送,接收端始终只处理一个消息;
  • 适应性强:不管是Timer定时触发,还是用户高频点击按钮,都能保证消息不丢失;
  • 容错性高:即使某个消息发送失败(比如网络中断),队列依然会处理后续消息(可根据需求添加重试逻辑)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 23:11:24