System.Threading.Timer 的问题 在线等。。。
System.Threading.Timer
假如说这个timer每200ms执行一次A
那么timer启动后是每200ms申请一个新线程执行A
还是就是在启动的时候申请一个新线程,然后以后的A都在这个线程里执行???
[解决办法]
首先看如下程序
- C# code
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication1{ class Program { static void callback(Object param) { string id = Guid.NewGuid().ToString(); //放一个随机产生的id用来区分每个callback调用,为了让输出看得更清楚 for (int i = 0; i < 5; i++) { Console.WriteLine("{0} loop {1}", id, i); System.Threading.Thread.Sleep(1000); } } static void Main(string[] args) { System.Threading.Timer t = new System.Threading.Timer(callback, null, 0, 1000); Console.Read(); } }}
[解决办法]
这是程序开始运行的一个输出片段:
c86e4a56-5f4d-4be9-9752-9af0a1387529 loop 0
c86e4a56-5f4d-4be9-9752-9af0a1387529 loop 1
d4e6da32-5254-4bb9-9a11-a1cf25863aa7 loop 0
c86e4a56-5f4d-4be9-9752-9af0a1387529 loop 2
d4e6da32-5254-4bb9-9a11-a1cf25863aa7 loop 1
ab622f0b-7f8d-40b1-b74e-1722e51eb86a loop 0
c86e4a56-5f4d-4be9-9752-9af0a1387529 loop 3
4edd3e9d-1c2b-4e16-be09-4fefc38c230c loop 0
d4e6da32-5254-4bb9-9a11-a1cf25863aa7 loop 2
ab622f0b-7f8d-40b1-b74e-1722e51eb86a loop 1
c86e4a56-5f4d-4be9-9752-9af0a1387529 loop 4
4edd3e9d-1c2b-4e16-be09-4fefc38c230c loop 1
47ac0157-43a4-4224-b4b9-770721ebbb57 loop 0
d4e6da32-5254-4bb9-9a11-a1cf25863aa7 loop 3
ab622f0b-7f8d-40b1-b74e-1722e51eb86a loop 2
5b7f4baa-858d-430e-8ccf-bb0ee90de88e loop 0
4edd3e9d-1c2b-4e16-be09-4fefc38c230c loop 2
47ac0157-43a4-4224-b4b9-770721ebbb57 loop 1
35c7f4a4-a528-47d8-b0b9-5cc1d25c1089 loop 0
d4e6da32-5254-4bb9-9a11-a1cf25863aa7 loop 4
ab622f0b-7f8d-40b1-b74e-1722e51eb86a loop 3
5b7f4baa-858d-430e-8ccf-bb0ee90de88e loop 1
4edd3e9d-1c2b-4e16-be09-4fefc38c230c loop 3
47ac0157-43a4-4224-b4b9-770721ebbb57 loop 2
35c7f4a4-a528-47d8-b0b9-5cc1d25c1089 loop 1
5dbb47cf-3444-47bf-8c4c-9b5ea2a22941 loop 0
ab622f0b-7f8d-40b1-b74e-1722e51eb86a loop 4
5b7f4baa-858d-430e-8ccf-bb0ee90de88e loop 2
4edd3e9d-1c2b-4e16-be09-4fefc38c230c loop 4
47ac0157-43a4-4224-b4b9-770721ebbb57 loop 3
35c7f4a4-a528-47d8-b0b9-5cc1d25c1089 loop 2
5dbb47cf-3444-47bf-8c4c-9b5ea2a22941 loop 1
e143eda8-0790-49cb-a685-b9c2dab7573b loop 0
5b7f4baa-858d-430e-8ccf-bb0ee90de88e loop 3
70adbb9b-90c2-4924-90e9-31d53441efa1 loop 0
a42a5128-dd26-48fb-9d53-3dc2996dcad1 loop 0
35c7f4a4-a528-47d8-b0b9-5cc1d25c1089 loop 3
e143eda8-0790-49cb-a685-b9c2dab7573b loop 1
5b7f4baa-858d-430e-8ccf-bb0ee90de88e loop 4
47ac0157-43a4-4224-b4b9-770721ebbb57 loop 4
70adbb9b-90c2-4924-90e9-31d53441efa1 loop 1
5dbb47cf-3444-47bf-8c4c-9b5ea2a22941 loop 2
9cf82d63-25d9-441d-adee-828ad1874b5c loop 0
a42a5128-dd26-48fb-9d53-3dc2996dcad1 loop 1
35c7f4a4-a528-47d8-b0b9-5cc1d25c1089 loop 4
e143eda8-0790-49cb-a685-b9c2dab7573b loop 2
70adbb9b-90c2-4924-90e9-31d53441efa1 loop 2
5dbb47cf-3444-47bf-8c4c-9b5ea2a22941 loop 3
5edc9ca3-2715-48d4-bfb6-c90341b6a84c loop 0
9cf82d63-25d9-441d-adee-828ad1874b5c loop 1
a42a5128-dd26-48fb-9d53-3dc2996dcad1 loop 2
e143eda8-0790-49cb-a685-b9c2dab7573b loop 3
70adbb9b-90c2-4924-90e9-31d53441efa1 loop 3
5dbb47cf-3444-47bf-8c4c-9b5ea2a22941 loop 4
ada6dc4b-7774-4cd1-a202-3ed89a25955a loop 0
5edc9ca3-2715-48d4-bfb6-c90341b6a84c loop 1
9cf82d63-25d9-441d-adee-828ad1874b5c loop 2
a42a5128-dd26-48fb-9d53-3dc2996dcad1 loop 3
e143eda8-0790-49cb-a685-b9c2dab7573b loop 4
70adbb9b-90c2-4924-90e9-31d53441efa1 loop 4
ffb316ad-1aa2-443c-9b3f-9de9dbbbcfd2 loop 0
ada6dc4b-7774-4cd1-a202-3ed89a25955a loop 1
5edc9ca3-2715-48d4-bfb6-c90341b6a84c loop 2
9cf82d63-25d9-441d-adee-828ad1874b5c loop 3
a42a5128-dd26-48fb-9d53-3dc2996dcad1 loop 4
ffb316ad-1aa2-443c-9b3f-9de9dbbbcfd2 loop 1
9124b616-d923-4a49-94f5-7bf12ff01c55 loop 0
ada6dc4b-7774-4cd1-a202-3ed89a25955a loop 2
5edc9ca3-2715-48d4-bfb6-c90341b6a84c loop 3
9cf82d63-25d9-441d-adee-828ad1874b5c loop 4
ffb316ad-1aa2-443c-9b3f-9de9dbbbcfd2 loop 2
9124b616-d923-4a49-94f5-7bf12ff01c55 loop 1
858e2132-933c-405e-9a3a-def3da8f949f loop 0
ada6dc4b-7774-4cd1-a202-3ed89a25955a loop 3
5edc9ca3-2715-48d4-bfb6-c90341b6a84c loop 4
7ce11d51-fa1f-4517-9c49-3e05ec88cc79 loop 0
ffb316ad-1aa2-443c-9b3f-9de9dbbbcfd2 loop 3
9124b616-d923-4a49-94f5-7bf12ff01c55 loop 2
858e2132-933c-405e-9a3a-def3da8f949f loop 1
ada6dc4b-7774-4cd1-a202-3ed89a25955a loop 4
7ce11d51-fa1f-4517-9c49-3e05ec88cc79 loop 1
bdb14d26-2829-44f5-bb04-09fe5eb90a56 loop 0
ffb316ad-1aa2-443c-9b3f-9de9dbbbcfd2 loop 4
9124b616-d923-4a49-94f5-7bf12ff01c55 loop 3
858e2132-933c-405e-9a3a-def3da8f949f loop 2
7ce11d51-fa1f-4517-9c49-3e05ec88cc79 loop 2
bdb14d26-2829-44f5-bb04-09fe5eb90a56 loop 1
40712cdd-cf7f-4074-8b09-64f6ef1a3f9a loop 0
9124b616-d923-4a49-94f5-7bf12ff01c55 loop 4
858e2132-933c-405e-9a3a-def3da8f949f loop 3
7ce11d51-fa1f-4517-9c49-3e05ec88cc79 loop 3
bdb14d26-2829-44f5-bb04-09fe5eb90a56 loop 2
40712cdd-cf7f-4074-8b09-64f6ef1a3f9a loop 1
4f118828-90dd-499c-827b-197abf4125e1 loop 0
858e2132-933c-405e-9a3a-def3da8f949f loop 4
7ce11d51-fa1f-4517-9c49-3e05ec88cc79 loop 4
bdb14d26-2829-44f5-bb04-09fe5eb90a56 loop 3
40712cdd-cf7f-4074-8b09-64f6ef1a3f9a loop 2
4f118828-90dd-499c-827b-197abf4125e1 loop 1
283c1582-6f8b-4383-84f3-e7e8ddf244b3 loop 0
bdb14d26-2829-44f5-bb04-09fe5eb90a56 loop 4
40712cdd-cf7f-4074-8b09-64f6ef1a3f9a loop 3
4f118828-90dd-499c-827b-197abf4125e1 loop 2
283c1582-6f8b-4383-84f3-e7e8ddf244b3 loop 1
7d8bc8b7-90bc-4f7d-8cd6-305080c379b5 loop 0
40712cdd-cf7f-4074-8b09-64f6ef1a3f9a loop 4
4f118828-90dd-499c-827b-197abf4125e1 loop 3
283c1582-6f8b-4383-84f3-e7e8ddf244b3 loop 2
7d8bc8b7-90bc-4f7d-8cd6-305080c379b5 loop 1
2e8ba890-55d2-4f4c-8d61-e4986f3aef57 loop 0
...
如果你能看懂这个验证你问题的方法,并且以后此类问题可以不求人的话,那就善莫大焉了。
[解决办法]
困了。
给一个使用消息通知主线程,并且让主线程同步运行消息的例子。注意这个代码没有严格测试,只是给你点思路:(类似Control.Invoke)
- C# code
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace ConsoleApplication1{ class Program { static void callback(Object param) { lock (msg) { msg.Enqueue(OnTimer); } e.Set(); } static void OnTimer() { string id = Guid.NewGuid().ToString(); for (int i = 0; i < 5; i++) { Console.WriteLine("{0} loop {1}", id, i); Thread.Sleep(1000); } } static Queue<Action> msg = new Queue<Action>(); static EventWaitHandle e = new EventWaitHandle(false, EventResetMode.AutoReset); static void Main(string[] args) { Timer t = new Timer(callback, null, 0, 1000); while (true) { List<Action> actions = new List<Action>(); lock (msg) { while (msg.Count > 0) { actions.Add(msg.Dequeue()); } } actions.ForEach(x => x()); e.Reset(); e.WaitOne(); } } }}
------解决方案--------------------
可以简单(用眼睛)测试一下:
- C# code
using System;using System.Threading;namespace ConsoleApplication1{ class Program { static void Main(string[] args) { System.Threading.Timer t = new System.Threading.Timer(delegate { Console.WriteLine("Timer {0}", Thread.CurrentThread.GetHashCode()); Thread.Sleep(5000); }, null, 0, 200); Console.WriteLine("主线程 {0}", Thread.CurrentThread.GetHashCode()); Console.ReadKey(); } }}
[解决办法]
[解决办法]
System.Threading.Timer t = new System.Threading.Timer(callback, null, 0, 1000);
就是间隔调用事件
[解决办法]
我稍微加点注释,不是很复杂的
- C# code
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace ConsoleApplication1{ class Program { //我们在callback中不直接调用定时器处理函数,而是将要处理的函数作为委托放入队列中 static void callback(Object param) { lock (msg) { msg.Enqueue(OnTimer); } //激活主线程 e.Set(); } //真正的定时器处理函数 static void OnTimer() { string id = Guid.NewGuid().ToString(); for (int i = 0; i < 5; i++) { Console.WriteLine("{0} loop {1}", id, i); Thread.Sleep(1000); } } //这个队列保存所有待处理的定时器函数的委托 static Queue<Action> msg = new Queue<Action>(); //定义一个线程事件,用来同步主线程和定时器线程 static EventWaitHandle e = new EventWaitHandle(false, EventResetMode.AutoReset); static void Main(string[] args) { Timer t = new Timer(callback, null, 0, 1000); //主程序不断循环 while (true) { //从队列中读取没有处理的定时器处理函数 List<Action> actions = new List<Action>(); lock (msg) { while (msg.Count > 0) { actions.Add(msg.Dequeue()); } } //这是关键,我们是在主程序里面调用定时器实际的处理函数,它之前被定时器放在了队列中 actions.ForEach(x => x()); //将线程事件对象重置,并且主线程休眠等待,直到队列中有新的要处理的函数 e.Reset(); e.WaitOne(); } } }}