c#多線程實現定時執行代碼與lock鎖操做

總結如下三種方法,實現c#每隔一段時間執行代碼:html

方法一:調用線程執行方法,在方法中實現死循環,每一個循環Sleep設定時間;c#

方法二:使用System.Timers.Timer類;函數

方法三:使用System.Threading.Timer;post

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

 

參考:this

http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813928.htmlspa

http://www.cnblogs.com/zxtceq/p/5667281.html.net

================================================================================線程

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 ;   //任務代碼 仍是在執行。。。。我想問我怎麼作 才能夠把這些阻塞了線程馬上釋放掉。簡單的意思就是馬上中止它?code

-----------------------------------------------------------htm

#16 得分:55回覆於: 2008-05-07 19:16:48

LZ是這樣的:你的fTimer每秒鐘都會調用一次DoTask,且同一時間只會有一個DoTask在運行,若是此時已有一個DoTask在運行,那麼後面的將被lock在那裏等着
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();
        }
    }
}

-------------------------------------------------

一、下面只解釋你的問題,並非達到你目的的最好方法。

二、Threading.Timer的工做方式是這樣的。每次時鐘到點時,Timer從線程池中取出一個線程來運行回調函數。若是該回調函數在下次時鐘到點前還沒來得及結束,那麼,可能會有多個線程同時在執行該函數。若是線程池中沒有空閒的線程可用,回調函數就要排隊等候。

三、Timer被取消後,它就再也不安排新的回調函數,可是已經在運行的,或已經在排隊的回調函數並無被取消。因此當你fTimer.Dispose();中止了時間後,任務代碼還在執行。

四、改進的方法。首先判斷一下當前線程池中剩餘可用線程的數目,若是小於必定數量,回調函數馬上返回。這樣能夠減小排隊的回調函數。
其次,設置一個‘工做中’的標誌,若是回調函數看到該標誌被放倒了,它也應該馬上返回。

五、即便通過如上改進後,Timer被取消後,線程池中線程也不會馬上完成 - 正在作‘任務代碼’的那個線程得把任務做完了纔有機會觀察到‘工做中’標誌。不過從這時起,全部回調函數將迅速返回。

六、若是你程序退出了,線程池整個就被中止了,固然你全部的任務代碼也就被中止了。若是你的任務代碼沒有須要清理的東西,這也是一種關閉方式。

    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/

以上信息只篩選一部分,查看完整版的能夠直接查看出處給出的地址。

相關文章
相關標籤/搜索