首页 > 编程语言 >C#中线程和定时器的使用记录

C#中线程和定时器的使用记录

时间:2023-01-07 13:12:05浏览次数:39  
标签:定时器 Console C# private 程和 WriteLine msg new public

记录学习代码。

使用线程,创建一个消息队列阻塞等待消息。

使用定时器,每隔一秒钟发送一条消息。

监听键盘Esc按键实现程序退出。

代码如下:

  1 using System;
  2 using System.Collections.Concurrent;
  3 using System.Collections.Generic;
  4 using System.Linq;
  5 using System.Text;
  6 using System.Threading;
  7 using System.Threading.Tasks;
  8 
  9 namespace TimerDemo
 10 {
 11     internal class Program
 12     {
 13         public enum MessageId
 14         {
 15             None = 0,
 16             Terminate,
 17         }
 18         // 使用结构体,因为demo数据很简单
 19         public struct TaskMessage
 20         {
 21             public MessageId id;
 22             public string description;
 23             public override string ToString()
 24             {
 25                 return "ID: " + id.ToString() + ", " + description+ ")";
 26             }
 27         }
 28 
 29         private Thread threadSender;
 30         private Thread threadReceiver;
 31         private Timer timer;
 32         private volatile bool terminatable;
 33         // 使用并发安全的队列
 34         private ConcurrentQueue<TaskMessage> taskMessages;
 35         // 这里用不到太复杂的功能,所以使用轻量级信号量即可
 36         private SemaphoreSlim msgAccessableSemp;
 37 
 38         public Program()
 39         {
 40             terminatable = false;
 41             taskMessages = new ConcurrentQueue<TaskMessage>();
 42             msgAccessableSemp = new SemaphoreSlim(0, 1);
 43 
 44             threadSender = new Thread(new ThreadStart(sender));
 45             threadReceiver = new Thread(new ThreadStart(receiver));
 46             threadSender.IsBackground = true;
 47             threadReceiver.IsBackground= true;
 48             threadSender.Start();
 49             threadReceiver.Start();
 50         }
 51 
 52         public void Wait()
 53         {
 54             threadSender.Join();
 55             threadReceiver.Join();
 56         }
 57 
 58         public void PostExistRequest()
 59         {
 60             taskMessages.Enqueue(new TaskMessage { id = MessageId.Terminate, description = DateTime.Now.ToString("hh:mm:ss.fff") });
 61             msgAccessableSemp.Release();
 62         }
 63 
 64         private void sender()
 65         {
 66             // 这里的发送线程,里面可以循环干活,但是我这里没有安排其他的工作
 67             #region 创建并启动定时器
 68             timer = new Timer(new TimerCallback((obj) =>
 69             {
 70                 if (terminatable)
 71                 {
 72                     // 除非主动停止,否则这个 timer 会一直周期性运行。
 73                     timer.Dispose();
 74                     timer = null;
 75                 }
 76                 else
 77                 {
 78                     // 插入消息到队列尾部并给出一个信号量通知对方干活
 79                     taskMessages.Enqueue(new TaskMessage { id = MessageId.None, description = DateTime.Now.ToString("hh:mm:ss.fff") });
 80                     msgAccessableSemp.Release();
 81                 }
 82             }), null, 0, 1000);
 83             #endregion
 84 
 85             Console.WriteLine("消息发送线程退出!");
 86         }
 87 
 88         private void messageHandle(in TaskMessage msg)
 89         {
 90             switch (msg.id)
 91             {
 92                 case MessageId.None:
 93                     Console.WriteLine(msg.ToString());
 94                     break;
 95                 case MessageId.Terminate:
 96                     terminatable = true;
 97                     break;
 98             }
 99 
100         }
101 
102         private void receiver()
103         {
104             TaskMessage msg;
105 
106             while (!terminatable)
107             {
108                 try
109                 {
110                     // 无限期等待信号量
111                     if (!msgAccessableSemp.Wait(600))
112                     {
113                         Console.WriteLine("\t无信号。");
114                     }
115 
116                     // 尝试从队列里面获取一条消息
117                     if (!taskMessages.IsEmpty && taskMessages.TryDequeue(out msg))
118                     {
119                         messageHandle(msg);
120                     }
121                     else
122                     {
123                         Console.WriteLine("\t无消息。");
124                     }
125                 }
126                 catch (Exception ex)
127                 {
128                     Console.WriteLine(ex.ToString());
129                 }
130             }
131 
132             // clear all messages.
133             int i = 0;
134             while (!taskMessages.IsEmpty)
135             {
136                 if (taskMessages.TryDequeue(out msg))
137                 {
138                     i ++;
139                     Console.WriteLine("线程结束,丢弃消息:" + msg.ToString());
140                 }
141             }
142             if (0 < i)
143             {
144                 Console.WriteLine("总计丢弃了 " + i + " 条消息。");
145             }
146             Console.WriteLine("消息接收线程退出!");
147         }
148 
149         static void Main(string[] args)
150         {
151             Console.WriteLine("启动程序");
152 
153             Program p = new Program();
154 
155             Console.WriteLine("主线程会等待全部子线程结束才会退出。");
156 
157             while (true)
158             {
159                 Console.WriteLine("你可以按Esc键结束程序。");
160                 try
161                 {
162                     ConsoleKeyInfo ki = Console.ReadKey(true);
163                     if (ki.Key == ConsoleKey.Escape)
164                     {
165                         // 发送消息结束程序
166                         p.PostExistRequest();
167                         break;
168                     }
169                 }
170                 catch (Exception ex)
171                 {
172                     Console.WriteLine("等待输入按键时检测到如下异常:");
173                     Console.WriteLine(ex.ToString());
174                 }
175             }
176 
177             p.Wait();
178             Console.WriteLine("程序结束。");
179         }
180     }
181 }

运行结果截图:

 

 《完》

标签:定时器,Console,C#,private,程和,WriteLine,msg,new,public
From: https://www.cnblogs.com/ssdq/p/17032484.html

相关文章

  • StringCbCatW与StringCchCatW的区别
    仔细看官方文档里,区别主要在第二个参数:StringCchCatW的cbDest:以字节为单位StringCchCatW的cchDest:以字符为单位大家根据实际情况选择合适的函数。附:StringCbCat、Stri......
  • mysql 服务异常crash 原因收集
    1.打开文件描述符数超出限制,造成crash重启,ERROR信息,提示toomanyopenfiles02022-06-27T08:03:56.201006+08:000[Warning][MY-012152][InnoDB]Openfiles407ex......
  • 【哈希表】LeetCode 350. 两个数组的交集 II
    题目链接350.两个数组的交集II思路建立两个哈希表分别统计nums1和nums2中每个数字出现的个数,然后同时遍历两个哈希表,对两个对位元素取其最小值count,将count数......
  • Vmware Vcenter&Vmware Horizon漏洞检测与利用一条龙
    VmwareVcenter&VmwareHorizon漏洞检测与利用一条龙 文章作者:[email protected] 1、VmwareVcenter漏洞被动检测我们可以利用BurpSuite软件结合插件对VmwareVcen......
  • 【哈希表】LeetCode 49. 字母异位词分组
    题目链接49.字母异位词分组思路如果一对字符串是字母异位词,那么他们经过排序之后,应该是相等的。利用这一特点,我们通过哈希表建立排序后字符串到原字符串列表的映射,不......
  • C语言程序设计课程设计[2023-01-07]
    C语言程序设计课程设计[2023-01-07]C语言程序设计课程设计要求一、课程设计目的1.进一步掌握和利用C语言进行程设计的能力;2.进一步理解和运用结构化程设计的思想和......
  • ubunut安装qtcreater
    安装gcc1kxb@kxb:~$gcc-v23Command'gcc'notfound,butcanbeinstalledwith:45sudoaptinstallgcc67kxb@kxb:~$sudoaptinstall......
  • CAS原理
    1.CAS基础1.1CAS操作原理 CAS:compareandswapCAS操作包含三个操作数:内存位置(V)、预期原值(A)、更新值(B); 2Atomic原子类JDK5之后新增并发包java.util.concurrent......
  • mysql 半同步的模式 after_commit 与 after_sync
    参考MySQL半同步after_sync与after_commit-墨天轮(modb.pro)1.after_commit提交流程:client-->executesql-->wrtieredolog-->writebinlog-->innodbstoragecommi......
  • C#基本循环逻辑语句
    基本逻辑包括:条件判断,循环控制语句,跳转等。如:if语句、swith语句、while语句、do…while语句、for语句、foreach语句、break语句、continue语句、goto语句、return语句、异......