简体   繁体   English

有没有更好的方法来实现多线程?

[英]Is there a better way to implement multithreading?

The source code portion below makes the CPU consumes high! 下面的源代码部分使CPU消耗很高! Is there a better way to implement multithreading? 有没有更好的方法来实现多线程?

// This application will run 24 hours 7 days per week
//     in server

static void Main(string[] args)
{
    const int NUM = 10;

    Thread[] t = new Thread[NUM];

    for (int i = 0; i < t.Length; i++)
        t[i] = new Thread(new ThreadStart(DoWork));

    foreach (Thread u in t)
        u.Start();
}

static void DoWork()
{
    while (true)
    {
        // Perform scanning work
        // If some conditions are satisfied,
        //     it will perform some actions
    }
}

The question is hard to answer if it isn't clear what's inside the while(true) spinning loop. 如果不清楚while(true)旋转循环中的内容,则很难回答这个问题。 If you start 10 threads where each one does spinning without any waits (using something like AutoResetEvent.WaitOne() , Thread.Sleep() , etc.), the CPU will be consumed - since you are asking the CPU for it. 如果您启动10个线程而每个线程都没有任何等待就旋转(使用AutoResetEvent.WaitOne()Thread.Sleep()等),则CPU将被消耗-因为您要向CPU请求。

To improve overall performance threads shouldn't spin if it isn't absolutely necessary to do - and in most cases it isn't. 为了提高整体性能,如果不是绝对必要的,则线程不应该旋转-在大多数情况下不是这样。 Threads should do their work and then if there aren't more work to do, they should go to sleep. 线程应完成其工作,然后如果没有更多工作要做,则应入睡。 They should be woken up only if they have more work items to process. 仅当它们有更多工作项目要处理时,才应将它们唤醒。 If your thread is running all the time - checking some conditions that are met only from time to time and if you have a mechanism to inform your thread that conditions are true - then the spinning is wasting of your CPU cycles. 如果您的线程一直在运行-检查不时满足的某些条件, 并且您有一种机制可以通知线程该条件为真 -那么旋转就浪费了CPU周期。

Conceptually a thread should work in this way. 从概念上讲,线程应以这种方式工作。

while(true)
{
    // Wait until a thread has something meaningful to do. Waiting can be done for instance by calling AutoResetEvent.WaitOne().

    // Do a meaningful work here.
}

If you do your thread code in this way, when a thread is waiting, it doesn't spend the CPU, so system is not overworked and other threads/processes can do their work. 如果以这种方式执行线程代码,则当线程正在等待时,它不会占用CPU,因此系统不会过度工作,其他线程/进程也可以完成其工作。

The principal question here is, if you have some kind of notification mechanism that allows your thread to wake up when a new work item arrives. 这里的主要问题是,如果您具有某种通知机制,当新工作项到达时,该通知机制允许线程唤醒。 For instance, most IO operations like TCP sockets, HTTP communication, reading from files, etc. support asynchronous communication that allows your thread to go to sleep and awake only if new data arrive. 例如,大多数IO操作(例如TCP套接字,HTTP通信,从文件读取等)都支持异步通信,该异步通信允许线程仅在收到新数据时进入睡眠和唤醒状态。

On the other hand, if you don't have such mechanism - for instance you are using a 3rd party library that doesn't notify you when something meaningful happened, you have to do some kind of spinning. 另一方面,如果您没有这样的机制-例如,您正在使用一个第三方库,该库在发生有意义的事情时不会通知您,则您必须进行某种旋转。 But even it this case, the question is, how often do you need to check if conditions were met - so there is some work to do. 但是即使是这种情况,问题仍然是,您需要多久检查一次是否满足条件-因此需要做一些工作。

If let say, you need to check only every second if conditions were met, add Thread.Sleep(1000) calls to your thread code. 如果可以说,您仅需每秒检查是否满足条件,则将Thread.Sleep(1000)调用添加到线程代码中。 This will greatly increases overal performance. 这将大大提高总体性能。 Even Thread.Sleep(0) is much better then wait-less spinning. 甚至Thread.Sleep(0)等待旋转好得多。

One important note here. 这里有一个重要的注意事项。 In modern C#, threads should not be used as your primary asynchronous programming mechanism. 在现代C#中,不应将线程用作您的主要异步编程机制。 Using task based asynchronous programming using class Task is much easier to implement, especially if you are using await-async C# keywords and in most cases leads to better performance. 使用class Task使用基于任务的异步编程更容易实现,尤其是在使用await-async C#关键字的情况下,并且在大多数情况下会导致更好的性能。

Tasks use threads internally creating new ones if there are too many work items to process with current number of threads and releasing threads, if there isn't enough work to do. 如果有太多的工作项无法使用当前数量的线程处理,则任务会在内部使用线程创建新线程,如果没有足够的工作要做,则释放线程。 Optimal number of threads reduces overal memory consumption. 最佳线程数减少了总内存消耗。

In these days virtually all standard .NET APIs support task based asynchronous programming so it should be your primary tool how to achieve paralel execution of your code. 如今,几乎所有标准.NET API都支持基于任务的异步编程,因此如何实现代码的并行执行应该成为您的主要工具。

Here is some example of task based asynchronous programming. 是基于任务的异步编程的一些示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM