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秒,我认为客户端断开连接.
这是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,以防客户端永远不发送心跳.