gpt4 book ai didi

c# - 保持定时器类型的线程

转载 作者:太空宇宙 更新时间:2023-11-03 17:54:02 25 4
gpt4 key购买 nike

我很难自己解决这个问题,因此在这里提问。我有一个在远程机器上安装客户端的应用程序客户端通过套接字进行报告。

我正在尝试创建一个保持计时器。这意味着客户端将每 1 分钟向服务器发送一次问候消息。如果服务器在保持计时器内没有从客户端收到问候数据包,则客户端将被删除。我可以和一个客户一起做...但对于多个我无法弄清楚。我正在考虑为每个连接到服务器的新客户端创建一个线程。然后在该线程内启动一个保持计时器。但是我如何通过线程区分客户端以及如何在从客户端收到 hello 数据包时重置保持计时器。

我想为每个 hello 数据包创建一个新线程并停止旧线程。但我不知道这将占用多少 CPU 资源

如果你不明白我的问题,请直说,我会尽量解释你不明白的地方。

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

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

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

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

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

解决方案 D)将计时器存储在字典中 public Dictionary timersDict = new Dictionary();并且循环在收到的 hello 数据包上的字典中找到引用并重置该计时器。?

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

解决方案

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

当服务器收到一条问候消息时,它会将时间戳与客户端的 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)
{

}
}

基本上我会遍历已连接客户端的列表,如果最后收到的问候消息早于 9 秒,我会考虑断开客户端连接。

最佳答案

这是 Reactive Extensions 的完美应用。这是您可以尝试的快速控制台应用程序示例(添加 Nuget 包 Rx-Main)。它通过要求您为他们的 ID 输入一个整数来模拟客户。在看到特定 ID 后 timeToHold 过去后,订阅中的操作将运行。

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();
}

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

关于c# - 保持定时器类型的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16586040/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com