C# 使用多线程如何传递两个以上参数的实现方法(附示例)

简介:

某些情况下当我们启动一个线程的时候会向该线程传递参数,有时除了功能上需要之外,我觉得还有就是为了我们能管理好启动的线程组(当然,只开一两个线程什么的也谈不上不好管理了,我说的线程组是指10+的线程,我们很难去主动控制的)。

因为刚接触C#,所以还没有在C#下用过多线程去实现某些功能。通过学习我发现单纯的去启动线程很容易,反而是想要往线程中传一些参数变得有点说道了,这里我想说传入参数的数量为>=2。不过我们还是一步一步的来,带大家过一遍C#下的多线程怎么搞。

以上一篇讲的网络通信的例子,把整个过程走一遍。这里网络通信只是作为一个讲解的示例,依旧是在控制台(Console)程序下实现的。

当Server端想要能与多个Client端进行连通的话,就必须用到多线程机制,我的思路:当程序启动后,Server端自己开一个专门用于进行监听的线程,这样主程序如果想做其他事也就不耽误了。当监听线程检测到有连接的请求,就为这个IP单独创建一个新的Socket(我们暂时称为SA Socket)进行通信用,当然,这个SA通信的内容(比如:收发消息)就是在一个新的线程或者两个(我们暂时称为TA线程)里实现的了,这个时候就需要我们往TA线程里传入SA的专有ID,让TA线程只专门为SA服务。之后的就依次类推了。

下面创建一个监听线程,这也是一个C#下最简单的多线程使用——创建多线程

1
2
Thread ListenThread =  new  Thread( new  ThreadStart(ServerListener));
ListenThread.Start();

对,就是这么easy,Thread构造函数里的参数类型为ThreadStart,这个东西官方解释是一个委托(啊,这里就不讲委托了,好像是C#特有的吧?反正我理解就是一个函数指针类型的东西或者是说某函数的别名,至于如何关联方法与委托,就是用new 委托名(函数名)的方法),表示此线程开始执行时要调用的方法。

关于委托大家可以下载http://down.51cto.com/data/1155877这个PPT,第229页处有详细讲解,简单易懂。

如上所说,在监听线程里我会创建一个监听的socket,然后有连接的话,会返回一个新的Socket对象,看代码:

1
2
3
4
5
6
7
//用于连接通道的socket,我默认创建了5个,也就是说与Server端最多只能连通5个socket
Socket[] CommunicationSocket =  new  Socket[5];
//index来维护所创建的socket数组
int  index = 0;
…省略…
//如有Client进行连接,返回一个新的socket
CommunicationSocket[index] = ListenSocket.Accept();

接下来就是本篇的关键部分了,由于我已经创建好了一个用于通信的CommunicationSocket,所以现在需要去创建一个独立的线程,用于专门为这个新的Socket作通信使用,而我传入的参数就是CommunicationSocket这个对象以及这个对象在socket数组中的位置index。

既然new ThreadStart()只能传入一个方法名,而没有给我们传参数的地方,那么针对于这个情况,我们需要用点小技巧,那就是使用类,看代码:

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
//消息操作类,用于传入线程
public  class  MessageHandler
{
      Socket socket =  null ;
      int  index = 0;
      bool  StopFlag =  false ;
      public  MessageHandler(Socket socket,  int  index)
      {
         this .socket = socket;
         this .index = index;
         Console.WriteLine( "线程"  this .index +  "号被创建!" );
      }
      //接收线程调用的函数
      public  void  ReceiveMessage()
     {
         byte [] buffer = newbyte[1024*4];
         string  message =  null ;
         try
         {
             while  (!StopFlag)
             {
                 int  result =  this .socket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                 if  (result < 0)
                 {
                     break ;
                 }
                 message = System.Text.Encoding.UTF8.GetString(buffer);
                 Console.Write( "Client("  + DateTime.Now.ToShortTimeString() +  "):"  + message.Trim());
                 Console.WriteLine();     
             }
          }
           catch  (System.Exception ex)
           {
               Console.WriteLine(ex.ToString()); this .socket.Close();
           }
     }
     //发送线程调用的函数
     public  void  SendMessage()
     {
         byte [] buffer = newbyte[1024 * 4];
         string  message =  null ;
         try
         {
             while  (!StopFlag)
             {
                 message = Console.ReadLine();
                 if  (message.ToLower().Equals( "byebye" ))
                 {
                     StopFlag =  true ;
                 }
                 buffer = System.Text.Encoding.UTF8.GetBytes(message);
                 this .socket.Send(buffer);     
              }
          }
          catch  (System.Exception ex)
          {                    
             Console.WriteLine(ex.ToString()); this .socket.Close();
          }
     }
}

这是我自己定义的消息操作类,大家看看,这个类的里面即实现了利用socket发送消息,也实现了接收消息的方法。写到这大家有没有来点灵感呢?再继续往下看:

1
2
3
4
5
6
7
8
//如果出现新的socket通道,那么分别创建一个该通道的接收线程与发送线程
//创建 MessageHandler类的对象,同时将参数传入到该对象中去,该实例的方法用于作为线程的目标方法
MessageHandler MsgHandler =  new  MessageHandler(CommunicationSocket[index], index);
ReceiveThread[index] =  new  Thread( new  ThreadStart(MsgHandler.ReceiveMessage));
ReceiveThread[index].Start();
SendThread[index] =  new  Thread( new  ThreadStart(MsgHandler.SendMessage));
SendThread[index].Start();
index++;

这样就实现了往线程里传递1个以上的参数了。

这里主要就是展示一下如何去传多个参数,对于多线程的管理等细节上还是有很多漏洞的,所以大家挑干的来就好了。

另外我附上原码,跟文章中的有点出路,主要是在文章中我对一些变量名称稍加进行了修改,便于大家看代码。

最后要说的是在C#多线程中传递一个参数的时候,有另外的专门方法,记得也是跟委托有关,不过具体我只是当时看了一下,这会儿已经记不得了,感兴趣的朋友可以去搜一下,不过话说回来,既然都会传多个参数了,传一个参数的话应该也很好搞定的。j_0015.gifj_0015.gifj_0015.gif

希望能帮到有需要的人。










本文转自 我不会抽烟 51CTO博客,原文链接:http://blog.51cto.com/zhouhongyu1989/1410687,如需转载请自行联系原作者

目录
相关文章
|
1月前
|
机器学习/深度学习 监控 算法
局域网行为监控软件 C# 多线程数据包捕获算法:基于 KMP 模式匹配的内容分析优化方案探索
本文探讨了一种结合KMP算法的多线程数据包捕获与分析方案,用于局域网行为监控。通过C#实现,该系统可高效检测敏感内容、管理URL访问、分析协议及审计日志。实验表明,相较于传统算法,KMP在处理大规模网络流量时效率显著提升。未来可在算法优化、多模式匹配及机器学习等领域进一步研究。
39 0
|
4月前
|
Java
线程池的核心参数有哪些 ?
corePoolSize 核心线程数量 maximumPoolSize 最大线程数量 keepAliveTime 线程保持时间,N个时间单位 unit 时间单位(比如秒,分) workQueue 阻塞队列 threadFactory 线程工厂 handler 线程池拒绝策略
|
6月前
|
JSON C# 数据格式
【Azure Function】C#独立工作模式下参数类型 ServiceBusReceivedMessage 无法正常工作
Cannot convert input parameter 'message' to type 'Azure.Messaging.ServiceBus.ServiceBusReceivedMessage' from type 'System.String'.
145 73
|
7月前
|
缓存 安全 Java
【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)
单例模式下,“饿汉模式”,“懒汉模式”,单例模式下引起的线程安全问题,解锁思路和解决方法
|
7月前
|
Java 程序员 调度
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获
|
8月前
|
Java
线程池七大参数
核心线程数:线程池中的基本线程数量 最大线程数:当阻塞队列满了之后,逐一启动 最大线程的存活时间:当阻塞队列的任务执行完后,最大线长的回收时间 最大线程的存活时间单位 阻塞队列:当核心线程满后,后面来的任务都进入阻塞队列 线程工厂:用于生产线程
|
8月前
|
JSON 程序员 C#
使用 C# 比较两个对象是否相等的7个方法总结
比较对象是编程中的一项基本技能,在实际业务中经常碰到,比如在ERP系统中,企业的信息非常重要,每一次更新,都需要比较记录更新前后企业的信息,直接比较通常只能告诉我们它们是否指向同一个内存地址,那我们应该怎么办呢?分享 7 个方法给你!
217 2
|
8月前
|
C# UED SEO
C# 异步方法async / await任务超时处理
通过使用 `Task.WhenAny`和 `Task.Delay`方法,您可以在C#中有效地实现异步任务的超时处理机制。这种方法允许您在指定时间内等待任务完成,并在任务超时时采取适当的措施,如抛出异常或执行备用操作。希望本文提供的详细解释和代码示例能帮助您在实际项目中更好地处理异步任务超时问题,提升应用程序的可靠性和用户体验。
333 3
|
9月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
82 2
|
2月前
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
91 0