简体   繁体   English

启用的计时器不打勾

[英]Enabled timer does not tick

I am writing a simple tcp communication program in c#.我正在用 c# 编写一个简单的 tcp 通信程序。 What i want is to start the timer by enabling it when client receieves a certain message.我想要的是通过在客户端收到特定消息时启用它来启动计时器。 Problem is, timer does not tick when its enabled.问题是,定时器在启用时不会滴答作响。 I am using System.Windows.Forms.Timer.我正在使用 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")));
        }
        
    }

Since this is a UI program you need to be careful to avoid blocking the UI thread.由于这是一个 UI 程序,您需要小心避免阻塞 UI 线程。

In your example the Receive will probably block the UI thread until there is some data.在您的示例中, Receive可能会阻塞 UI 线程,直到有一些数据。 And it will continue to do so if the timer is already enabled, or if it does not receive the required message.如果计时器已经启用,或者它没有收到所需的消息,它将继续这样做。 This will prevent the UI from doing other things, like updating the graphics, or to handle mouse and keyboard events.这将阻止 UI 执行其他操作,例如更新图形或处理鼠标和键盘事件。 Never block the UI thread永远不要阻塞 UI 线程

To avoid this you need to either use asynchronous programming or background threads.为避免这种情况,您需要使用异步编程或后台线程。 Since background threads require a fairly good understanding of thread safety I would recommend the async approach.由于后台线程需要对线程安全有相当好的理解,我建议使用异步方法。

I do not have any complete example, and such an example might be counter productive if this is homework, but the overall approach should be:我没有任何完整的例子,如果这是家庭作业,这样的例子可能会适得其反,但总体方法应该是:

  1. Create a TcpClient from a TcpListnerTcpListner创建 TcpClient
  2. Get a NetworkStream from the TcpClient.GetStream()TcpClient.GetStream()获取 NetworkStream
  3. Wrap this stream inside a streamReader, and use ReadLineAsync() to read lines.将此流包装在 streamReader 中,并使用ReadLineAsync()读取行。 Use whatever text-encoding you want when creating your reader.在创建阅读器时使用您想要的任何文本编码。
  4. await the returned task to get the actual string.等待返回的任务以获取实际的字符串。

You can do this inside an infinite loop inside an async method.您可以在异步方法内的无限循环中执行此操作。 This should not block, since the await will let the UI thread do other things while it waits for data.不应该阻塞,因为await会让 UI 线程在等待数据时做其他事情。 Keep in mind to wrap the contents of the method in a try/catch, since it is otherwise possible for exceptions to get lost.请记住将方法的内容包装在 try/catch 中,否则异常可能会丢失。

This should be appropriate for a simple application demonstrating the concepts, but for real world usage I would highly recommend using a library to handle communication.这应该适用于演示概念的简单应用程序,但对于实际使用,我强烈建议使用库来处理通信。 That will most likely be much easier to use.这很可能会更容易使用。

Note that some methods returning tasks lie, and are really synchronous methods pretending to be async.请注意,一些返回任务的方法是谎言,并且是假装异步的真正同步方法。 This will obviously not work, but it can be difficult to tell from the documentation, so it is often easiest to just try.这显然行不通,但从文档中很难分辨,因此尝试通常是最简单的。

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

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