C# 程序设计用timer还是多线程?

pujitan978 2018-11-13 04:25:43
有100台设备,通过网线连到服务器,服务器每20秒,对所有设备采集次数据,然后保存到数据库。
如果一个线程20秒内采集不完数据。
下面是我打算的二种设计,请大家帮看看,怎么设计好。那种好
1)一种方法是起多个线程,每个线程采集几台数据。将来扩展1000台是,追加线程数。
2)另一种方法启动多个周期timer,每20秒一个周期。

怎么设计好呢?还是有其他设计方法。
...全文
637 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhiluan7665 2019-02-15
  • 打赏
  • 举报
回复
不建议用timer.c#中很少使用线程了,都是用task,代码效率更高些,使用从线程池中分配一个,不使用回收。
风衣笛手 2018-11-28
  • 打赏
  • 举报
回复
可以看看微软的Orleans框架
sdfgrtyu 2018-11-21
  • 打赏
  • 举报
回复
.net里面的多线程就是声明式的编程方式,底层的控制就是TaskScheduler
可以利用Plinq进行操作
enaking 2018-11-21
  • 打赏
  • 举报
回复
如果你这个运行周期很短的话,就是连接,处理业务,结束,建议使用timer。如果比较长比如3秒钟以上,建议使用线程。
sdfgrtyu 2018-11-21
  • 打赏
  • 举报
回复
使用线程池就是要保证不阻塞,如果在线程池里进行阻塞,那就会破坏性能。
sdfgrtyu 2018-11-21
  • 打赏
  • 举报
回复
关键就是:用最少的线程做更多的事情,但是客户端的话,增加了线程但是保证了系统的可响应型,这个也可以,,,,
liusa1997 2018-11-21
  • 打赏
  • 举报
回复
一般用多线程吧,放在线程池里面,当设备增加时,扩大线程池就行了
sgyiliya 2018-11-19
  • 打赏
  • 举报
回复
public bool CheckIPAndPort(string ipAddress, int portNum)
{
IPAddress ip = IPAddress.Parse(ipAddress);
try
{
IPEndPoint point = new IPEndPoint(ip, portNum);
using (Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
sock.Connect(point);
sock.Close();
return true;
}
}
catch (SocketException e)
{
return false;
}
}

public void FiveSecondMethod(string _ip, int _port)
{
CheckIPAndPort(_ip, _port);
}
public bool CallWithTimeout(Action<string, int> action, string _ip, int _port, int timeoutMilliseconds)
{
bool _OK = false;

Thread threadToKill = null;
Action wrappedAction = () =>
{
threadToKill = Thread.CurrentThread;
action(_ip, _port);
};

IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds))
{
_OK = true;
wrappedAction.EndInvoke(result);
}
else
{
threadToKill.Abort();
_log.Error("连接:" + _ip.Trim() + "端口:" + _port.ToString() + ",已经超过限制时间。");
_OK = false;
}

return _OK;
}
#endregion



写一个方法FunA调用:
if (CallWithTimeout(FiveSecondMethod, Form1.Array_A_IP, 8866, 2000) == true)
{
//在2秒内成功执行完了任务,这里可以继续后续动作
}


在线程池里面把这个方法FunA执行,一个设备用一个线程,一个线程最多执行20秒时间,具体安排多少个线程来执行,你可以指定一个初始值比如50个线程,其他 的事情,线程池会帮你去做的。

供你参考
threenewbee 2018-11-17
  • 打赏
  • 举报
回复
timer有好几个版本,system.threading.timer就是多线程的
bigbear_gd 2018-11-16
  • 打赏
  • 举报
回复
如果是三菱的机器,必须前面的线程释放掉端口以后你才能开始下一个线程的采集,其实它还是排队的,而且和CPU的核数有关,

而发那科的机器就没有这个问题
mk_lucifer 2018-11-16
  • 打赏
  • 举报
回复
引用 10 楼 summergo123321 的回复:
看你读的是什么了,一般是不要前台运行IO操作,因为很多io操作消耗时间很多,会导致前台线程阻塞过长时间出现卡顿。。。但是如果读的非常快也可以凑活用,但写程序不应该凑活。。。
设备数量和线程数量无关,你通讯一万台也可以后台单线程。。。做法很简单

foreach(Device e in Devs){
if(Device.IsConnected){
object o= e.ReadData();
Save(e.ID,o);
}
}

代码没有什么固定格式,如果读1万台单线程阻塞方式20秒能解决,那么就没问题,如果有问题,10个线程每个读1000个可以么?还有一种解决办法就是异步IO,异步读到一个数据(都会有事件通知),然后就扔线程池执行,然后用信号量限制下线程最大数量就OK,用什么办法都是根据实际情况而定,最好的办法当然是异步IO,但逻辑对于初学者来说非常不友好。。。最容易理解和处理的就单线程阻塞方式,一个个来了,时间赶得上就没问题。。。
xian_wwq 2018-11-16
  • 打赏
  • 举报
回复
1.timer和线程相比,建议使用线程。因为看现有的逻辑,
timer存在超时重入的问题。

2.线程和线程池相比,线程池的开销要小的多
3楼大神已经简要说过了。
除非有特定需求,使用短连接比长连接难度小,问题少。
mk_lucifer 2018-11-16
  • 打赏
  • 举报
回复
看你读的是什么了,一般是不要前台运行IO操作,因为很多io操作消耗时间很多,会导致前台线程阻塞过长时间出现卡顿。。。但是如果读的非常快也可以凑活用,但写程序不应该凑活。。。
设备数量和线程数量无关,你通讯一万台也可以后台单线程。。。做法很简单

foreach(Device e in Devs){
if(Device.IsConnected){
object o= e.ReadData();
Save(e.ID,o);
}
}

sdfgrtyu 2018-11-15
  • 打赏
  • 举报
回复
很明显啊,你需要两种一起用。
可以先并行连接,首先就是异步发送,然后开启一个定时器,判断超时,还要支持取消,然后并发处理,然后加一个锁,处理竞争消息,然后就是下一次循环????
大然然 2018-11-15
  • 打赏
  • 举报
回复
100台机器,开N个线程,N不是随意想弄5个,10个,100个的,最优线程数和你CPU核数有关,假设为5个
那么
1线程处理1---20号机器
2线程处理21--40号机器
。。。。。
5线程处理81-100号机器

牧歌ing 2018-11-13
  • 打赏
  • 举报
回复
xuzuning 2018-11-13
  • 打赏
  • 举报
回复
方案2是不可取的,增加了编程难度,还没解决20秒超市问题
其实多线程只需 new Task(() => {你的采集代码}).Start(); 就可以了,没必要犯愁的
token不能为空 2018-11-13
  • 打赏
  • 举报
回复
多个周期timer每20秒一个周期执行 和多线程分别采集不同机器看起来没什么区别吧 你timer执行的肯定也是分开采集机器,不然怎么保证更快速采集完呢 可以试试Task,我没有试过1000个线程的业务场景
  • 打赏
  • 举报
回复
在编写程序之前,你首先要问那些根本不懂编程的人,那些一个真正的用户,假设批量采集数据时,假设一个设备经过20秒还没有上报完毕数据,那么你的上位机是不是要开始采集数据。这首先由你自己回答。 然后才是技术实现问题。
  • 打赏
  • 举报
回复
正规的说法是叫做上位机,而不是服务器。因为“服务器”这个词儿是有歧义的。许多这类系统网络架构中,是一个100个服务器1个客户端的架构,你的那个所谓的"服务器“实际上是一个客户端,而100台设备才是服务器。所以说”上位机“可以避免让内行说起来你会很”尴尬“。 接下来看,”每20秒对所有设备采集一次数据“,那么你应该采用 .net 系统线程池来自动化地分配任务线程,而不是什么”自己启动线程“。以现在比较时髦的写法,就是
Task.Run(()=>
{
    ..........
});
这样返回一个异步任务。 如果只知道自己 new 什么 Thread 对象实例,那基本上是至少15 年前的古老的知识了。因为系统线程池自动管理任务线程(ThreadPool.QueueUserWorkItem)在 .net 1.1 中就是比较基本的知识了。 在你了解了 .net 系统会自动优化线程调度策略之后,再来看任务的顺序操作控制策略,就能比较容易理解。其实两种概念需要你来自己把握。其一,是一个任务20秒未结束之前,是否要启动对同一个设备的另一次采集;其二,是否要等到一个采集任务结束(不管是否超过了20秒钟)之后才开始下一个采集任务。这是你首先要在业务逻辑上自己回答清楚的问题。总是有人先不回答业务逻辑设计问题,反而先来纠结什么编程技术语句,希望通过套取别人的代码来替他自己来回答业务逻辑设计问题。这其实就养成了把狗屁技术凌驾在业务逻辑之上的习惯!真正来说,业务为主旨为目标,而技术只是次要的东西。 如果一个采集没有完成就不应该开始下一个采集,那么你就不可能用什么”20秒定时Timer“的逻辑来说明业务需求,这在”大白话“上在语言上就是说不通的,连语文都没有通讯又怎么描述程序设计呢?!所以业务描述上不可能自相矛盾。真正在那里纠结、争吵的,往往都是用技术概念来浑浑噩噩地当作业务需求来说的人。 那么至于哪一种设计”更好“,其实首先是业务上的考量。跟技术无关。如果你只是问哪一种设计在业务上更好,这是显而易见的。
加载更多回复(2)
第1章 C#编程基础  实例1 Hello C#!  实例2 HeyGuy  实例3 预定义类型  实例4 类型转换  实例5 选择语句  实例6 循环语句  实例7 跳转语句  实例8 数组  实例9 枚举与结构类型  实例10 类  实例11 位运算  实例12 操作符重载  实例13 虚方法  实例14 委托  实例15 属性  实例16 异常处理  实例17 链表  实例18 回文数  实例19 汉诺塔  实例20 冒泡排序  实例21 插入排序  小结 第2章 界面编程  实例22 Hello Form  实例23 主菜单  实例24 上下文菜单  实例25 工具栏  实例26 状态栏  实例27 进度条  实例28 滑块控件  实例29 单选框和复选框  实例30 列表框和组合框  实例31 列表视图  实例32 树视图  实例33 Timer控件  实例34 Splitter控件  实例35 时钟控件和日历控件  实例36 MDI窗口  实例37 窗体继承  实例38 自制控件  实例39 使用自制控件  实例40 模式与非模式  实例41 会跑的按钮  实例42 绘制背景  实例43 可调窗口  实例44 托动窗体  实例45 电子便条  实例46 计算器界面设计  实例47 计算器功能实现  实例48 小闹钟  小结 第3章 图形与图像处理  实例49 简单画图  实例50 使用OnPaint绘制图形  实例51 绘制贝赛尔曲线  实例52 显示图像  实例53 消除图片背景  实例54 底片滤镜  实例55 浮雕效果  实例56 显示字体  实例57 特效字  实例58 旋转图片  实例59 打印  小结 第4章 线程 第5章 文件处理和系统操作 第6章 数据库编程 第7章 网络编程 第8章 Web应用程序的开发 第9章 多媒体 第10章 安全性 第11章 设计模式 第12章 杂例

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧