保持定时器类型线程

Vis*_*ean 1 c# multithreading timer system.reactive

我很难为自己找出这个因此在这里问.我有一个应用程序,它在远程计算机上安装客户端,客户端通过套接字报告.

我试图创建一个保持计时器.这意味着客户端将每1分钟向服务器发送一个问候消息.如果服务器在保持定时器内没有从客户端获取hello数据包,则客户端将被删除.我可以用一个客户端做得很好......但对于多个我无法理解它.我正在考虑创建一个线程foreach连接到服务器的新客户端.然后在该线程内部启动一个保持计时器..但我如何区分客户端与线程,以及如何重置保持计时器如果从客户端收到一个hello数据包.

我想为每个hello数据包创建一个新线程并停止旧数据包.但我不知道这将是多么密集的cpu

如果你不明白我的问题,请说出来,并试着解释你不理解的任何事情.

哪种解决方案更好?解决方案A)每次打开hello数据包时启动一个新线程并停止旧线程?(每40秒) - 来自100个客户

解决方案B)在此处插入更好的可扩展解决方案.

解决方案C)我可以访问我动态创建的线程内的计时器吗? - 我在所有动态创建的线程上都有唯一的线程名称.

public void _clientholdtimer()
    {          
    holdtimer = new Timer();
    holdtimer.Interval = SECtoMS(Settings.Default.Hold);
    holdtimer.Elapsed += holdtimer_Elapsed;          
    }
Run Code Online (Sandbox Code Playgroud)

当我从客户端收到一个与线程同名的hello数据包时重置它?

解决方案D)将定时器存储在字典中公共字典timersDict = new Dictionary(); 并且循环在dict中找到关于hello数据包接收重置该定时器的引用.

foreach(var item in timersDict)
                            {
                                if(item.Key == stripip(client.RemoteEndPoint.ToString()))
                                    TimerReset(item.Value);
                            }   
Run Code Online (Sandbox Code Playgroud)

设置远程主机应用程序,每隔3秒向服务器发送一条"hello"消息.在服务器上创建一个计时器,每1秒发生一次经过的事件.设置一个静态值来保存一个int,它决定了,在我认为远程机器死了多久之前,我选择了9秒.

当服务器收到hello消息时,它将时间戳存储在列表中,并带有客户端的ip地址.

在timer_elapsed事件上

void holdtimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {

        try
        {
            if (server.Clients.GetAllItems().Count != 0)
            {
                foreach (IScsServerClient _client in server.Clients.GetAllItems())
                {
                    string ipaddr = stripip(_client.RemoteEndPoint.ToString());
                    bool containsentry = _clientlist.Any(item => item.ipadress == ipaddr);
                    if (containsentry)
                    {
                        foreach (Scsserverclient entry in _clientlist.Where(entry => entry.ipadress == ipaddr))
                        {
                            if ((DateTime.Now - TimeSpan.FromSeconds(Settings.Default.Hold)) > entry.lasthello &&
                                entry.isConnect != "Disconnected")
                            {
                                entry.client.Disconnect();                              
                            }
                        }
                    }                                             
                }

            }
        }
        catch (Exception ex)
        {

        }
    }
Run Code Online (Sandbox Code Playgroud)

基本上我通过连接客户端列表运行,如果最后收到的hello消息超过9秒,我认为客户端断开连接.

Jam*_*rld 7

这是Reactive Extensions的完美应用程序.这是一个快速的应用程序示例,您可以尝试(添加Nuget包Rx-Main).它通过要求您为其ID输入整数来模拟客户端.自从看到特定ID后经过timeToHold后,将运行Subscribe中的操作.

使用Synchronize很重要 - 从RX版本2开始,如果没有Synchronize调用,Subject OnNext不是线程安全的.

多亏了RX,这个解决方案在使用定时器和线程方面非常高效.

注意:我在我的博客上添加了更详细的解释:http://www.zerobugbuild.com/?p = 230

public void Main()
{
    var clientHeartbeats = new Subject<int>();

    var timeToHold = TimeSpan.FromSeconds(5);

    var expiredClients = clientHeartbeats
        .Synchronize()
        .GroupBy(key => key)
        .SelectMany(grp => grp.Throttle(timeToHold));

    var subscription = expiredClients.Subscribe(
        // in here put your disconnect action
        i => Console.WriteLine("Disconnect Client: " + i));

    while(true)
    {
        var num = Console.ReadLine();
        if (num == "q")
        {
            break;
        }
   // call OnNext with the client id each time they send hello
        clientHeartbeats.OnNext(int.Parse(num));
    }   

    // if you need to tear down you can do this
    subscription.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

附录:哦,如果您的服务器负责启动客户端,您可能希望在启动客户端时从服务器发送OnNext,以防客户端永远不发送心跳.

  • 是否足够酷,你可能会投票?;) (2认同)