【问题标题】:create multiple threads and communicate with them创建多个线程并与它们通信
【发布时间】:2015-06-06 00:30:49
【问题描述】:

我有一个程序,它需要很长时间来初始化,但它的执行速度相当快。

它正在成为一个瓶颈,所以我想启动这个程序的多个实例(比如一个池),并让它已经初始化,这个想法是只传递它执行所需的参数,从而节省所有初始化时间。

问题是我只找到了如何启动传递参数的新进程:
How to pass parameters to ThreadStart method in Thread?

但我想正常启动进程,然后能够与它通信以向每个线程发送执行所需的参数。

我发现的最好的方法是创建多个线程来初始化程序,然后使用一些通信机制(例如命名管道,因为它都在同一台机器上运行)能够传递这些参数并触发执行程序(例如,其中一个触发器可能会中断无限循环)。

我在问是否有人可以建议一个更优化的解决方案,而不是我想出的那个。

【问题讨论】:

  • 我们真的不知道您的解决方案是什么,因为您没有向我们展示它的代码。基本上可以通过公共数据变量来向线程传递参数。您通常使用某种互斥锁来管理对这些变量的访问。在您的情况下,如果您只是在一个线程中读取数据并在另一个线程中写入数据,那么这甚至可能没有必要。

标签: c# multithreading


【解决方案1】:

我建议你不要乱用直接 Thread 用法,而使用 TPL,如下所示:

foreach (var data in YOUR_INITIALIZATION_LOGIC_METHOD_HERE)
{
    Task.Run(() => yourDelegate(data), //other params here);
}

更多关于Task.RunMSDNStephen Cleary blog

【讨论】:

    【解决方案2】:

    Process != Thread

    线程存在于进程中,而进程是操作系统中的整个程序或服务。

    如果你想加快你的应用程序初始化,你仍然可以使用线程,但现在我们使用 Task Parallel Library 使用它们,使用 Task Asynchronous Pattern

    为了通信任务(通常是线程),您可能需要实现某种状态机(某种基本工作流程),您可以在其中检测某些任务何时进行并根据任务状态(正在运行、失败、已完成...)。

    无论如何,您不需要命名管道或类似的东西来通信任务/线程,因为一切都在同一个父进程中。也就是说,您需要使用常规编程方法来执行此操作。我的意思是:使用 C# 和线程同步机制以及某种应用内消息传递。

    一些非常基本的想法...

    .NET 有一个 List<T> 集合类。您应该设计一个协调器类,您可以在其中添加一些接收消息类(由您设计)的列表,如下所示:

    public enum OperationType { DataInitialization, Authentication, Caching }
    
    public class Message 
    {
        public OperationType Operation { get; set; }
        public Task Task { get; set; }
    }
    

    然后开始所有并行初始化任务,将每个人添加到协调器类中的列表中:

    Coordinator.Messages.AddRange
    (
        new List<Message> 
        {
             new Message 
             { 
                 Operation = Operation.DataInitialization, 
                 Task = dataInitTask
             },
             ..., // <--- more messages
        }
    );
    

    添加所有带有待处理初始化任务的消息后,您可以在代码中的某处等待初始化以这种方式异步结束:

    // You do a projection of each message to get an IEnumerable<Task>
    // to give it as argument of Task.WhenAll
    await Task.WhenAll(Coordinator.Messages.Select(message => message.Task));
    

    当这一行等待完成所有初始化时,您的 UI(即主线程)可以继续工作并显示某种加载动画或谁知道是什么(无论如何)。

    也许您可以更进一步,不要等待所有任务,而是等待一组任务允许您的用户开始使用您的应用,而其他非关键任务结束......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-06
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多