控制台应用程序中运行的计时器没有其他功能

时间:2018-11-20 12:13:00

标签: c# timer console-application

我正在异步套接字侦听器控制台应用程序中使用system.Timers计时器。 我希望计时器每40秒运行一次,并检查客户端设备的连接状态。

一旦计时器启动,服务器套接字将不再监听(不再等待更多连接),并且连接的第一台设备始终只能接收数据。当我从网络中删除设备并再次连接时,没有任何反应。没有其他功能正在运行。 这是计时器的代码-

IPStatusTimer = new System.Timers.Timer(35000);
        IPStatusTimer.Elapsed += IPStatusTimer_Elapsed;
        IPStatusTimer.AutoReset = true;
        IPStatusTimer.Enabled = true;

  private static void IPStatusTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        Console.WriteLine("Inside Timer");
        if (connectedClient > 0)
        {
            foreach (KeyValuePair<string, int> i in IPStatus)
            {
                if (i.Value == 1)
                {
                    IPStatus[i.Key] = 0;
                }
                else if (i.Value == 0)
                {
                    Decode dr = new Decode();
                    string m = dr.offlineMessage();
                    if (Clients.Count > 0)
                    {
                        foreach (KeyValuePair<int, StateObject> c in Clients)
                        {
                            if (((IPEndPoint)c.Value.workSocket.RemoteEndPoint).Address.ToString() == i.Key)
                            {
                                Clients.Remove(c.Key);
                            }
                        }
                        SendMessage(i.Key, m);
                    }
                }
            }
        }
    }

计时器不应该影响我的其他功能。它应该在后台安静地运行,直到应用程序正常运行为止。

编辑:(在上面的代码中)如果CLients.Count> 0添加,则只会从CLients中删除项目,因此那里不会有任何异常。

只要有连接,我都会将Stateobject添加到字典中,以便在需要时可以向所有客户端广播数据。

    public static void AcceptCallback(IAsyncResult ar)
    {
        connectedClient++;
        // Signal the main thread to continue.  
        allDone.Set();
        // Get the socket that handles the client request.  
        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);
        string ip = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
        Console.WriteLine("ip   " + ip);
        // Create the state object.  
        StateObject state = new StateObject();
        state.buffer = new byte[StateObject.BufferSize];
        Clients.Add(connectedClient, state);
        if (IPStatus.ContainsKey(ip))
            IPStatus[ip] = 1;
        else
        IPStatus.Add(ip, 1);
        Console.WriteLine(" Total Connected client : " + connectedClient);
        state.workSocket = handler;           
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
            new AsyncCallback(ReadCallback), state);
    }       

如您所见。如果客户端返回网络并且服务器始终处于侦听模式,则它应该接受连接,并且状态对象应再次添加到Client(字典对象)。这应该不是问题。客户端一连接好,我就给IPStatus(字典对象)一个值1,因为它表示客户端在线。

然后在我的readCallBack()中,每当我从任何客户端接收到数据时,然后在我的字典中,我都会在IPStatus中再次将其值设置为1。

 public static void ReadCallback(IAsyncResult ar)
    {
        string content = string.Empty;

        // Retrieve the state object and the handler socket  
        // from the asynchronous state object.  
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;
        // Read data from the client socket.   
        int bytesRead = handler.EndReceive(ar);
        int i = 0;
        string ip = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
        if (IPStatus.ContainsKey(ip))
        {
            IPStatus[ip] = 1;
            }
}

然后当Timer运行时,如果任何IP的值为1,则将其设置为0。因此,如果下次运行Timer并获得值0,则表示它在过去35秒内未从客户端收到任何数据。客户不再在线。 ReadCallback和所有状态都使用StateObject而不是Clients(字典对象)来进行。因此,如果我要从“客户端”中删除任何项目,则在“任何新连接”启动时会再次添加该项目。

我希望你们的情况变得更加清楚。

1 个答案:

答案 0 :(得分:0)

感谢@ rs232 ...指出异常的原因。 是字典对象抛出错误。因此在对字典进行读写操作之前要先使用锁(对象)。

lock (Clients)
                    {
                        if (Clients.Count > 0)
                        {
                            foreach (KeyValuePair<string, StateObject> c in Clients)
                            {
                                if (c.Value.workSocket == handler)
                                {
                                    Clients.Remove(c.Key);
                                    Console.WriteLine("Client automatically disconnected");
                                    Decode dr = new Decode();
                                    string m = dr.offlineMessage();
                                    SendMessage(ip, m);
                                    break;
                                }
                            }
                        }
                    }

以及该页面上其他任何考虑计时器问题的人。上面的代码(在问题中)非常好,可以按要求工作。您可以从中获取参考。