如何实现按顺序为每个新建C#线程分配自定义输入消息
解决多线程按顺序输入自定义消息的问题
你的问题根源很明确:每个线程启动后立刻调用Console.ReadLine(),导致多个线程同时抢占控制台输入资源,所以才会出现一堆输入提示同时弹出来的混乱情况。要实现逐个输入每个线程的消息再让线程工作,咱们换个思路:先在主线程按顺序收集好所有消息,再把对应消息传递给每个线程,而不是让线程自己去读输入。
给你两种可行的修改方案:
方案1:用Lambda捕获局部变量传递参数
这种写法比较简洁,注意要避开C#闭包的坑:
Console.WriteLine("enter how many"); int threadsToRun = Convert.ToInt32(Console.ReadLine()); // 第一步:主线程逐个收集每个线程的消息,单线程执行绝对不会乱 List<string> threadMessages = new List<string>(); for (int i = 0; i < threadsToRun; i++) { Console.WriteLine($"Enter message for threadname{i}:"); string message = Console.ReadLine(); threadMessages.Add(message); } // 第二步:启动线程,把对应的消息和线程名传递过去 for (int i = 0; i < threadsToRun; i++) { // 必须把循环变量i复制到局部变量,否则会因为闭包捕获的是变量引用,导致线程拿到错误的索引 int currentThreadIndex = i; Thread thread = new Thread(() => DoWork(threadMessages[currentThreadIndex], $"threadname{currentThreadIndex}")); thread.Start(); } // 修改后的DoWork,直接接收消息和线程名参数 static void DoWork(string message, string threadName) { while (true) { Thread.Sleep(2000); Console.WriteLine("Thread#{0} is now working!", threadName); Console.WriteLine(message); } }
方案2:用自定义对象传递参数(适合参数较多的场景)
如果后续需要给线程传递更多参数,这种方式更清晰:
// 定义一个类来封装线程需要的所有数据 public class ThreadWorkData { public string Message { get; set; } public string ThreadName { get; set; } } static void Main(string[] args) { Console.WriteLine("enter how many"); int threadsToRun = Convert.ToInt32(Console.ReadLine()); // 先收集所有消息 List<string> threadMessages = new List<string>(); for (int i = 0; i < threadsToRun; i++) { Console.WriteLine($"Enter message for threadname{i}:"); threadMessages.Add(Console.ReadLine()); } // 启动线程并传递封装好的数据 for (int i = 0; i < threadsToRun; i++) { int currentThreadIndex = i; ThreadWorkData data = new ThreadWorkData { Message = threadMessages[currentThreadIndex], ThreadName = $"threadname{currentThreadIndex}" }; Thread thread = new Thread(DoWorkWithData); thread.Start(data); } } // 接收自定义对象参数的工作方法 static void DoWorkWithData(object dataObj) { ThreadWorkData workData = dataObj as ThreadWorkData; if (workData == null) return; while (true) { Thread.Sleep(2000); Console.WriteLine("Thread#{0} is now working!", workData.ThreadName); Console.WriteLine(workData.Message); } }
关键注意点:
- 主线程先完成所有输入:主线程是单线程执行,所以会严格按照
threadname0→threadname1→...的顺序提示输入,完全不会混乱。 - 避开闭包陷阱:如果直接在Lambda里用循环变量
i,线程启动时i可能已经被循环修改了,导致多个线程拿到同一个索引的值,所以必须把i复制到局部变量currentThreadIndex再捕获。
这样修改后,你就能先逐个输入每个线程的专属消息,所有消息输入完成后,线程才会开始各自的工作循环,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Doctuh
相关产品推荐
相关产品推荐

