You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现按顺序为每个新建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 05:22:36