创建多个线程并与之通信

时间:2015-04-01 11:22:18

标签: c# multithreading

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

它已经成为一个瓶颈,所以我想启动这个程序的多个实例(就像一个池)已经初始化它,并且想法只是为它的执行传递所需的参数,保存所有初始化时间。

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

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

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

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

2 个答案:

答案 0 :(得分:3)

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

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

有关MSDNStephen Cleary blog

Task.Run的更多信息

答案 1 :(得分:2)

Process!= Thread

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

如果您想加速应用初始化,您仍然可以使用线程,但现在我们使用Task Parallel LibraryTask 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(即主线程)可以继续工作并显示某种加载动画或谁知道什么(无论如何)。

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