繁体   English   中英

启用的计时器不打勾

[英]Enabled timer does not tick

我正在用 c# 编写一个简单的 tcp 通信程序。 我想要的是通过在客户端收到特定消息时启用它来启动计时器。 问题是,定时器在启用时不会滴答作响。 我正在使用 System.Windows.Forms.Timer。

        void ReceiveData()
    {
        int recv;
        string stringData;
        while (true)
        {
            recv = client.Receive(data);
            stringData = Encoding.ASCII.GetString(data, 0, recv);
            if (stringData == "/starttimer" & !timer1.Enabled)
            {
                timer1.Enabled = true;
                break;
            }

            
        }
    }

    Stopwatch player1timer = new Stopwatch();
    void timer1_Tick(object sender, EventArgs e)
    {
        if (player1timer.IsRunning)
        {
            pl1label.Text = Convert.ToDouble(2) - Convert.ToDouble(player1timer.Elapsed.Minutes.ToString("00")) + ":" +
          Convert.ToString(Convert.ToDouble(59) - Convert.ToDouble(player1timer.Elapsed.Seconds.ToString("00"))) + "." +
          Convert.ToString(Convert.ToDouble(999) - Convert.ToDouble(player1timer.Elapsed.Milliseconds.ToString("00")));
        }
        
    }

由于这是一个 UI 程序,您需要小心避免阻塞 UI 线程。

在您的示例中, Receive可能会阻塞 UI 线程,直到有一些数据。 如果计时器已经启用,或者它没有收到所需的消息,它将继续这样做。 这将阻止 UI 执行其他操作,例如更新图形或处理鼠标和键盘事件。 永远不要阻塞 UI 线程

为避免这种情况,您需要使用异步编程或后台线程。 由于后台线程需要对线程安全有相当好的理解,我建议使用异步方法。

我没有任何完整的例子,如果这是家庭作业,这样的例子可能会适得其反,但总体方法应该是:

  1. TcpListner创建 TcpClient
  2. TcpClient.GetStream()获取 NetworkStream
  3. 将此流包装在 streamReader 中,并使用ReadLineAsync()读取行。 在创建阅读器时使用您想要的任何文本编码。
  4. 等待返回的任务以获取实际的字符串。

您可以在异步方法内的无限循环中执行此操作。 不应该阻塞,因为await会让 UI 线程在等待数据时做其他事情。 请记住将方法的内容包装在 try/catch 中,否则异常可能会丢失。

这应该适用于演示概念的简单应用程序,但对于实际使用,我强烈建议使用库来处理通信。 这很可能会更容易使用。

请注意,一些返回任务的方法是谎言,并且是假装异步的真正同步方法。 这显然行不通,但从文档中很难分辨,因此尝试通常是最简单的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM