首页 > c# > 将消息发送到任务

将消息发送到任务 (Sending messages to Tasks)

2019-03-12 c#multithreading

问题

我正在编写一个程序,根据用户提供的某些条件显示mandelbrot集。由于计算时间很长(超过500毫秒),我决定使用多个线程。没有任何以前的经验,我已经设法通过使用System.Threading.Tasks类来完成它,它运行得很好。我唯一不喜欢的是,每次生成mandelbrot时,线程都会被创建然后被销毁

这是它如何工作的一个例子。每次调用该方法时,它都会创建线程(Tasks)。

for (int i = 0; i < maxThreads; i++) {
    int a = i;
    tasks[a] = Task.Factory.StartNew(() => generateSector(a));
}

我真的不知道它是如何影响性能的,但看起来创建和销毁线程的时间非常昂贵,并且让线程准备就绪并等待触发器消息会更高效,并且当它们完成时返回到那个等待的状态。可能是以下示例代码有助于理解这个想法。

for (int i = 0; i < maxThreads; i++)
    tasks[i].sendMessage("Start"); // Tells the running thread to begin its work

因此每个线程都会执行一个无限循环,等待它们被要求进行计算。然后,它将继续等待。像这样的东西:

// Into the method that a thread executes
while(true) {
    Wait(); // Waits for the start signal
    calculate(); // Do some calculations
}   // Go back to waiting

这会更有效吗?有没有办法做到这一点?

解决方法

听起来你正在尝试使用一组线程并设置一个系统来调度在这些线程上运行的工作。这是一个好主意,但事实上,它是一个很好的想法,它内置于.NET框架中,您不需要自己构建它。这实际上就是为任务制作的。

任务是一个相对轻量级的抽象,而不是由.NET运行时管理的线程池。线程是一个操作系统结构,相对较重,并且在线程之间启动,停止和上下文切换有点昂贵。创建任务时,它会调度该任务以在池中的下一个可用线程上执行,并且.NET运行时将根据是否有工作排队等待线程来自动增加和减小池的大小执行。如果需要,您可以自定义最小最大线程数,但通常这不是nessecary。

因此,通过简单地创建在单个工作单元的生命周期中存在的短期任务,他们已经将您的工作运行在托管的实际线程集合上。

问题

I am writing a program that shows the mandelbrot set depending on some conditions provided by the user. As the calculation takes long (more than 500 ms), I have decided to use more than one thread. Without any previous experience, I have managed to do it by using the System.Threading.Tasks class, which works just fine. The only thing that I don't like is that every time that the mandelbrot is generated, the threads are created and then destroyed.

This is an example of how it works. It creates the threads (Tasks) every time that the method is called.

for (int i = 0; i < maxThreads; i++) {
    int a = i;
    tasks[a] = Task.Factory.StartNew(() => generateSector(a));
}

I don't know really how that affects performance, but it looks like creating and destroying threads is time expensive, and that it would be more efficient to have the threads ready and waiting for a trigger message, and when they are done go back to that waiting state. May be the following example code is useful to understand this idea.

for (int i = 0; i < maxThreads; i++)
    tasks[i].sendMessage("Start"); // Tells the running thread to begin its work

So each thread would execute an infinite loop in which it waits until they are required to do calculations. Then, it would continue with waiting. Something like this:

// Into the method that a thread executes
while(true) {
    Wait(); // Waits for the start signal
    calculate(); // Do some calculations
}   // Go back to waiting

Would that be more efficient? Is there any way to do that?

解决方法

It sounds like you're trying to use a set of of threads and setting up a system for scheduling work to run on those threads. This is a great idea but in fact, it's so great of an idea that it's built into the .NET framework and you don't need to build it yourself. This is actually exactly what Tasks are made for.

Tasks are a relatively lightweight abstraction over the Thread Pool which is managed by the .NET Runtime. Threads are an operating-system construct that are relatively heavy and it's somewhat expensive to start, stop, and context-switch between threads. When you create a Task, it schedules that task to execute on a the next available thread in the pool and the .NET runtime will automatically increase and decrease the size of the pool based on whether there's work getting queued up and waiting for a thread to execute. You can customize the minimum and maximum thread counts if you need to but usually this is not nessecary.

So by simply creating short-lived Tasks that exist for the lifetime of the single unit of work, they're already going to have your work be run on a managed collection of actual threads.

相似信息