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

如何使用C#多线程执行控制台应用程序?

用C#多线程并行执行外部应用程序

嘿,看起来你已经写好了单线程重复执行外部程序的代码,但其实当前的实现还是串行执行的——因为在单个线程里每次启动进程后都调用了WaitForExit(),得等上一个进程跑完才会启动下一个。如果想真正利用多线程的并行优势,让多个外部程序同时跑,咱可以这么改:

首先先看看你现有的单线程代码:

public static void OneThread() { 
    DateTime startTime = DateTime.Now; 
    Thread t11 = new Thread(() => { 
        for (int i = 0; i <= 5; i++) { 
            var proc = new Process(); 
            proc.StartInfo.FileName = @"C:\Users\consoleapp.exe"; 
            proc.StartInfo.Arguments = "-v -s -a"; 
            proc.Start(); 
            proc.WaitForExit(); 
            var exitCode = proc.ExitCode; 
            proc.Close(); 
        } 
    }); 
    t11.Start(); 
    t11.Join(); 
    Console.WriteLine("execution 1 thread 5 times in {0} seconds", (DateTime.Now - startTime).TotalSeconds); 
}

方案1:用Thread类实现并行执行

我们可以创建多个线程,每个线程负责启动一次外部程序,然后等待所有线程完成。这样多个进程就能同时运行了:

public static void MultiThreadWithThreadClass()
{
    DateTime startTime = DateTime.Now;
    const int runTimes = 5;
    var threads = new List<Thread>();

    for (int i = 0; i < runTimes; i++)
    {
        // 注意:循环变量要捕获当前值,否则可能出现线程共享变量的问题
        int iteration = i;
        var thread = new Thread(() =>
        {
            // 用using自动释放Process资源,比手动Close更可靠
            using (var proc = new Process())
            {
                proc.StartInfo.FileName = @"C:\Users\consoleapp.exe";
                proc.StartInfo.Arguments = "-v -s -a";
                proc.Start();
                proc.WaitForExit();
                var exitCode = proc.ExitCode;
                // 加个锁保证控制台输出不乱序(可选)
                lock (Console.Out)
                {
                    Console.WriteLine($"Iteration {iteration} completed with exit code: {exitCode}");
                }
            }
        });
        threads.Add(thread);
        thread.Start();
    }

    // 等待所有线程执行完成
    foreach (var thread in threads)
    {
        thread.Join();
    }

    Console.WriteLine($"Multi-thread (Thread class) execution {runTimes} times in { (DateTime.Now - startTime).TotalSeconds } seconds");
}

方案2:用Task(推荐,更现代的异步方式)

在.NET里,Task是更推荐的异步/多线程编程模型,代码更简洁,还能利用Task的各种便捷API:

public static async Task MultiThreadWithTaskAsync()
{
    DateTime startTime = DateTime.Now;
    const int runTimes = 5;
    var tasks = new List<Task>();

    for (int i = 0; i < runTimes; i++)
    {
        int iteration = i;
        var task = Task.Run(() =>
        {
            using (var proc = new Process())
            {
                proc.StartInfo.FileName = @"C:\Users\consoleapp.exe";
                proc.StartInfo.Arguments = "-v -s -a";
                proc.Start();
                proc.WaitForExit();
                var exitCode = proc.ExitCode;
                lock (Console.Out)
                {
                    Console.WriteLine($"Iteration {iteration} completed with exit code: {exitCode}");
                }
            }
        });
        tasks.Add(task);
    }

    // 异步等待所有任务完成
    await Task.WhenAll(tasks);

    Console.WriteLine($"Multi-thread (Task) execution {runTimes} times in { (DateTime.Now - startTime).TotalSeconds } seconds");
}

额外注意事项

  • 资源释放:一定要用using包裹Process实例,因为它实现了IDisposable,using会自动帮你释放相关资源,避免内存泄漏。
  • 并发控制:如果外部程序不能同时运行太多实例(比如依赖同一个文件、端口),可以用SemaphoreSlim来限制并发数:
    // 限制最多同时运行3个进程
    var semaphore = new SemaphoreSlim(3);
    // 在每个任务里先等待信号量
    await semaphore.WaitAsync();
    try
    {
        // 执行进程代码
    }
    finally
    {
        semaphore.Release();
    }
    
  • 错误处理:建议给进程启动和执行的代码加上try-catch,避免单个进程的异常导致整个多线程逻辑崩溃。
  • 线程安全:像Console.WriteLine这种共享资源的操作,最好加锁或者用线程安全的方式输出,否则会出现乱码或者重叠输出的情况。

内容的提问来源于stack exchange,提问作者Neo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:51:31