c#多线程实现定时执行代码与lock锁操作
总结以下三种方法,实现c#每隔一段时间执行代码:
方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间;
方法二:使用System.Timers.Timer类;
方法三:使用System.Threading.Timer;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
using System; using System.Collections; using System.Threading; public class Test { public static void Main() { Test obj = new Test(); Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString()); //方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间 Thread thread = new Thread( new ThreadStart(obj.Method1)); thread.Start(); //方法二:使用System.Timers.Timer类 System.Timers.Timer t = new System.Timers.Timer(100); //实例化Timer类,设置时间间隔 t.Elapsed += new System.Timers.ElapsedEventHandler(obj.Method2); //到达时间的时候执行事件 t.AutoReset = true ; //设置是执行一次(false)还是一直执行(true) t.Enabled = true ; //是否执行System.Timers.Timer.Elapsed事件 while ( true ) { Console.WriteLine( "test_" + Thread.CurrentThread.ManagedThreadId.ToString()); Thread.Sleep(100); } //方法三:使用System.Threading.Timer //Timer构造函数参数说明: //Callback:一个 TimerCallback 委托,表示要执行的方法。 //State:一个包含回调方法要使用的信息的对象,或者为空引用(Visual Basic 中为 Nothing)。 //dueTime:调用 callback 之前延迟的时间量(以毫秒为单位)。指定 Timeout.Infinite 以防止计时器开始计时。指定零 (0) 以立即启动计时器。 //Period:调用 callback 的时间间隔(以毫秒为单位)。指定 Timeout.Infinite 可以禁用定期终止。 System.Threading.Timer threadTimer = new System.Threading.Timer( new System.Threading.TimerCallback(obj.Method3), null , 0, 100); while ( true ) { Console.WriteLine( "test_" + Thread.CurrentThread.ManagedThreadId.ToString()); Thread.Sleep(100); } Console.ReadLine(); } void Method1() { while ( true ) { Console.WriteLine(DateTime.Now.ToString() + "_" + Thread.CurrentThread.ManagedThreadId.ToString()); Thread.CurrentThread.Join(100); //阻止设定时间 } } void Method2( object source, System.Timers.ElapsedEventArgs e) { Console.WriteLine(DateTime.Now.ToString() + "_" + Thread.CurrentThread.ManagedThreadId.ToString()); } void Method3(Object state) { Console.WriteLine(DateTime.Now.ToString() + "_" + Thread.CurrentThread.ManagedThreadId.ToString()); } } |
参考:
http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813928.html
http://www.cnblogs.com/zxtceq/p/5667281.html
================================================================================
System.Threading.Timer fTimer = new System.Threading.Timer(new TimerCallback(TaskService.DoTask), new AutoResetEvent(false), 0, 1000);
public void DoTask(Object stateInfo)
{
lock (this)
{
//任务代码
}
}
当我 fTimer.Dispose();//停止了时间后,可以 任务代码 还在执行。经过我调式N次发现是在lock里阻塞了线程。当我
fTimer.Dispose()停止后即使把fTimer = null ; //任务代码 还是在执行。。。。我想问我怎么做 才可以把这些阻塞了线程立刻释放掉。简单的意思就是立刻停止它?
-----------------------------------------------------------
#16 得分:55回复于: 2008-05-07 19:16:48
LZ你这么做一是为了同一时间只做一个DoTask,二是为了保证执行的顺序吧?
实际上,当DoTask里的操作超过1秒时,后面的DoTask都会被lock在那里。比如我的fTimer运行了9秒多,那么应该有总共10个DoTask,假设DoTask要执行2秒钟,那么当你在9秒多停止fTimer的时候,实际上才运行到第5个DoTask(左右),后面还有5个DoTask被lock着呢
LZ可以看下这个
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Test t = new Test(); while (t.Enabled) ; Console.WriteLine("STOPING:" + t.Value); t.Stop(); Console.WriteLine("STOPPED:" + t.Value); Console.ReadLine(); } } public class Test { System.Threading.Timer fTimer; private int i = 0; System.Timers.Timer timer; public int Value { get { return i; } } public bool Enabled { get { return timer.Enabled; } } public Test() { fTimer = new System.Threading.Timer(new TimerCallback(this.DoTask), new AutoResetEvent(false), 0, 1000); timer = new System.Timers.Timer(10000); timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); timer.Enabled = true; } private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { timer.Enabled = false; } public void DoTask(Object stateInfo) { lock (this) { Console.WriteLine(i++); Thread.Sleep(2000); } } public void Stop() { fTimer.Dispose(); } } }
-------------------------------------------------
1、下面只解释你的问题,并不是达到你目的的最好方法。
2、Threading.Timer的工作方式是这样的。每次时钟到点时,Timer从线程池中取出一个线程来运行回调函数。如果该回调函数在下次时钟到点前还没来得及结束,那么,可能会有多个线程同时在执行该函数。如果线程池中没有空闲的线程可用,回调函数就要排队等候。
3、Timer被取消后,它就不再安排新的回调函数,但是已经在运行的,或已经在排队的回调函数并没有被取消。所以当你fTimer.Dispose();停止了时间后,任务代码还在执行。
4、改进的方法。首先判断一下当前线程池中剩余可用线程的数目,如果小于一定数量,回调函数立刻返回。这样可以减少排队的回调函数。
其次,设置一个‘工作中’的标志,如果回调函数看到该标志被放倒了,它也应该立刻返回。
5、即使经过如上改进后,Timer被取消后,线程池中线程也不会立刻完成 - 正在做‘任务代码’的那个线程得把任务作完了才有机会观察到‘工作中’标志。不过从这时起,所有回调函数将迅速返回。
6、如果你程序退出了,线程池整个就被停止了,当然你所有的任务代码也就被停止了。如果你的任务代码没有需要清理的东西,这也是一种关闭方式。
class TaskService { volatile bool running = true; public void DoTask(Object stateInfo) { int threadsLeft, dummy; ThreadPool.GetAvailableThreads(out threadsLeft, out dummy); if (threadsLeft < 2) return; //<---- lock (this) { if (!running) return; //<---- //任务代码 } } public void test() { using (System.Threading.Timer fTimer = new Timer(new TimerCallback(DoTask), null, 0, 1000)) { Console.ReadLine(); fTimer.Change(0, Timeout.Infinite); running = false; } Console.ReadLine(); } static void Main() { new TaskService().test(); } }
没有用lock和Timer的方法:
volatile bool running = true; public void DoTasks() { DateTime last = new DateTime(); while (running) { DateTime current = DateTime.Now; int elasped = (int) (current - last).TotalMilliseconds; last = current; if (elasped < 1000) { Thread.Sleep(Math.Min(1000, 1000 - elasped)); } //任务代码... } }
出处:http://bbs.csdn.net/topics/220079236/
以上信息只筛选一部分,查看完整版的可以直接查看出处给出的地址。
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/6474406.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
posted on 2017-02-27 15:28 jack_Meng 阅读(3744) 评论(0) 编辑 收藏 举报