求教一个多线程处理数据的问题

wc19840730 2018-08-21 04:14:24
不是写C#单机的,但是工作中因为有些需要自己写了个小东西用以处理工作,现在遇到一些问题,望比较了解的人对我进行一下指导。

写的是WINDOWS服务,没有其他的东西,一个定时器10秒触发一个任务。

代码如下:
  //定时器
CarryDataTimer = new System.Timers.Timer(10000);
CarryDataTimer.Elapsed += new System.Timers.ElapsedEventHandler(CarryDataTimer_Elapsed);
CarryDataTimer.Enabled = true;


  //任务
Thread CT = new Thread(new ThreadStart(CarryFromData));
CT.IsBackground = true;
CT.Start();




任务本身是处理一个数据库的存储过程,处理完会在数据上打个标志。

try
{
WriteLog("临时表抓取数据:" + DateTime.Now.ToString());
ConSql.Update("exec EQC_Com_GetBaseData '" + DateTime.Now.ToShortDateString() + "'", SaveSqlCon);
}
catch (Exception e)
{
WriteLog("错误:" + e.Message.ToString());
}


现在遇到的问题是因为客户数据库性能不一,这个存储过程不一定能在10秒内执行完。导致发生了并发处理,而应用逻辑上,有一个逻辑的依据是数据处理的先后次序。那么一旦遇到并发出现,就会出现逻辑上的问题(同时存在两份数据)。

我想问一下,有没有在技术上解决这个问题的办法,比如:能否做到上一次的线程没有执行完的情况下跳过这一轮。
...全文
211 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
wc19840730 2018-09-11
  • 打赏
  • 举报
回复
我不明白为啥都盯着多线程?

我只是三个任务开了三个线程啊,出问题的是单一线程耗时过长导致的下个线程会和上个线程同时处理数据时会产生冲突。

我加了个状态标志,标志未重置之前不新开线程。目前来看有效~~
wanghui0380 2018-08-21
  • 打赏
  • 举报
回复
排他锁是就你提出的问题而回答的

正常情况下,这个还是不必加锁,每10秒只是产生一个任务。这个没啥问题,不加锁也没有任何关系。

因为他是任务,他就可以是task,可以是task.continuewith,只要他们没有共享资源,他们可以并发存在
xuzuning 2018-08-21
  • 打赏
  • 举报
回复
首先,线程不会提高程序运行速度
只在如有可以平行运行的任务时,线程可利用程序等待 I/O 的间隙运行

既然你 应用逻辑上,有一个逻辑的依据是数据处理的先后次序
那么处理就不能分别赋予不同的线程

解决这个问题的办法就是 Lock
能否做到上一次的线程没有执行完的情况下跳过这一轮。的做法是违背 数据处理 流程的,我 #7 的回复作废
BXS_null 2018-08-21
  • 打赏
  • 举报
回复
加个消息列队
wc19840730 2018-08-21
  • 打赏
  • 举报
回复
引用 12 楼 yenange 的回复:
定时不要用 Thread, 定时器要精准, 控制也容易得多。


我没有用THREAD的定时器啊,我用的就是timer的定时器的定时啊。我只不过定时器到了以后触发一个线程里处理信息。

我想通过改动最少的方法达成目的,因为也不是一个核心业务,是一个辅助业务,改动代价要小一点。如果去掉线程那总会有不放心的情况发生。
吉普赛的歌 2018-08-21
  • 打赏
  • 举报
回复
定时不要用 Thread, 定时器要精准, 控制也容易得多。
wanghui0380 2018-08-21
  • 打赏
  • 举报
回复
微软自己有排他锁 Monitor

而这个排他锁,有tryEnter方法

有不懂的直接百度,这是基本锁,百度上很多介绍
wc19840730 2018-08-21
  • 打赏
  • 举报
回复
还有LOCK的应用场景是什么。

在有标志的情况下是否有必要应用LOCK?

比如
int i=0
try
{
if i=1
return
i=1
exec
i=0
}
catch{
i=0
}
wc19840730 2018-08-21
  • 打赏
  • 举报
回复
引用 8 楼 wanghui0380 的回复:
加锁就成,当然加锁默认是排队,如果是直接忽略,可以实在排他锁,可以尝试进入,进不去就扔掉,进的去就进


因不是做单机程序的所以很多基础并不清楚,所以请指教:
LOCK是锁的概念我明白了,你的意思是锁整个方法?还是运行过程中锁标志?

锁住整个方法的话,那么第二个线程启动运行此方法的时候,会等待第一个线程运行完解锁码?
wanghui0380 2018-08-21
  • 打赏
  • 举报
回复
加锁就成,当然加锁默认是排队,如果是直接忽略,可以实在排他锁,可以尝试进入,进不去就扔掉,进的去就进
xuzuning 2018-08-21
  • 打赏
  • 举报
回复
Lock

if 标志置位 then 返回
Lock() {
置位标志
任务代码
复位标志
}

wc19840730 2018-08-21
  • 打赏
  • 举报
回复
应该可以试试看,我的任务是三个。我只要做死三个标志即可。每个线程启动时更新,做完了置回原始状态。

我试一下。
吉普赛的歌 2018-08-21
  • 打赏
  • 举报
回复
引用 3 楼 wc19840730 的回复:
[quote=引用 1 楼 yenange 的回复:]
不要用线程, 用定时器。 参考: https://www.cnblogs.com/xuxiaoshuan/p/5385843.html


我的WINDOWS服务里有三个定时器。

因为我没写过WINDOWS服务,开线程执行方法是因为以前做CS的时候如果不开线程会卡,就沿用下来。

你的意思是,我这个WINDOWS里直接开三个定时器直接执行方法就可以了?[/quote]
嗯。
但始终面临重入。
重入的问题, 你参考上面的链接。
wc19840730 2018-08-21
  • 打赏
  • 举报
回复
引用 1 楼 yenange 的回复:
不要用线程, 用定时器。 参考: https://www.cnblogs.com/xuxiaoshuan/p/5385843.html


你给的这个文章里主要也是说用一个外部的标志来标识没有跑完吧。

我试试看。
wc19840730 2018-08-21
  • 打赏
  • 举报
回复
引用 1 楼 yenange 的回复:
不要用线程, 用定时器。 参考: https://www.cnblogs.com/xuxiaoshuan/p/5385843.html


我的WINDOWS服务里有三个定时器。

因为我没写过WINDOWS服务,开线程执行方法是因为以前做CS的时候如果不开线程会卡,就沿用下来。

你的意思是,我这个WINDOWS里直接开三个定时器直接执行方法就可以了?
晨易夕 2018-08-21
  • 打赏
  • 举报
回复
你这个线程有什么用。
吉普赛的歌 2018-08-21
  • 打赏
  • 举报
回复
不要用线程, 用定时器。 参考: https://www.cnblogs.com/xuxiaoshuan/p/5385843.html

110,535

社区成员

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

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

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