Advantage of using Thread.Start vs QueueUserWorkItem

后端 未结 9 1576
有刺的猬
有刺的猬 2020-11-28 12:49

In multithreaded .NET programming, what are the decision criteria for using ThreadPool.QueueUserWorkItem versus starting my own thread via new Thread() and Thread.Start()?

相关标签:
9条回答
  • 2020-11-28 12:59

    If you're creating your own threads, it makes sense to start them on first use and then let them hang around for a while in case you need them again - you make an idle thread wait on an event so you can reactivate it by signaling the event, and after a long enough time elapses, the thread will wake itself and exit, reclaiming the unused resources. By keeping a small number of idle threads ready to be reused, you reduce the overhead of constantly creating and destroying threads (which is significant for sufficiently short-lived operations).

    But this is basically what the thread queue already does for you - so you may as well use it. It's a solved problem.

    A similar debate used to happen in the C++ community about strings, believe it or not. Should we each write our own string class, or should we use std::string? The answer depends on whether you want to learn how to write a string class, or you're done with that and you want to get on with inventing something new.

    0 讨论(0)
  • 2020-11-28 13:00

    If your tasks are short you will most likely see much better performance by scheduling tasks on the thread pool via QueueUserWorkItem or BeginInvoke as you avoid the repeated cost of creating and destroying your own threads.

    The thread pool obviously pays for creating threads as well, but it reuses the threads, so you don't pay the cost per task.

    You may also want to take a look at Threading in C# (free ebook).

    0 讨论(0)
  • 2020-11-28 13:05

    Here's another advantage to using ThreadPool.QueueUserWorkItem.

    I have a winforms app which has a hearbeat. I originally implemented this using

                heartbeat = new Thread(HeartbeatDoWork);
            heartbeat.Start();
    

    Which works fine 98% of the time. However when the app is closed sometimes it doesn't 'die' properly, ie the process is still visible in task manager.

    To be brief, the heartbeat published an event and it was handling the event (CAB pub/sub) where it was 'getting stuck'.

    The fix was easy, just change to using this

                ThreadPool.QueueUserWorkItem(HeartbeatDoWork);
    

    I'm sure there's a few extra things I could do when spinning off my own thread and it to would be cleaned up properly, but this is simpler, faster and easier to understand...the ThreadPool does all the work for me.

    0 讨论(0)
  • 2020-11-28 13:07

    This discussion will interest you
    When should I not use the ThreadPool in .Net?

    0 讨论(0)
  • 2020-11-28 13:14

    I was gonna make this a comment, but it got too long.
    CodemonkeyKing seems to have hit on an important point, though not strongly enough in my opinion.

    There are lots of criteria you might use to describe code. Will it be used in a long running app or not? Winforms app or not? Is it a Server or client app? library or standalone exe? etc etc.

    Seems to me that if your code will run in a standalone app and you have control over all the surrounding code, then you can roll your own thread pool, start your own threads, and measure and manage the cost around thread startup, thread latency, and resource consumption. Or you could use the QUWI, but it won't kill your app either way. You are free to choose.

    On the other hand if your code is packaged as a library that may be used in a server -in ASP.NET, or maybe in a SQL CLR app, or a WCF Service - then it is a really bad idea to create threads. You need to use QUWI, or some other mechanism that exploits the built-in thread pool (like BackgroundWorker). If it is to be used in client-side apps with other libraries, once again, QUWI is required. Imagine that every library wanting to take advantage of multi-core computers rolled their own threads. There would be complete chaos in apps that used more than a few libraries. Rampant threads, all competing for the same resources. No central coordination of #threads vs # processors.

    Good hygeine demands that a library, whether it is to be consumed in client apps or server apps, uses the common threadpool, and that means QUWI.

    Last thing to realize is this;

    A managed thread is either a background thread or a foreground thread. Background threads are identical to foreground threads with one exception: a background thread does not keep the managed execution environment running. Once all foreground threads have been stopped in a managed process (where the .exe file is a managed assembly), the system stops all background threads and shuts down.

    Threads that belong to the managed thread pool (that is, threads whose IsThreadPoolThread property is true) are background threads. All threads that enter the managed execution environment from unmanaged code are marked as background threads. All threads generated by creating and starting a new Thread object are by default foreground threads.

    If you use a thread to monitor an activity, such as a socket connection, set its IsBackground property to true so that the thread does not prevent your process from terminating.

    from the MSDN site.

    0 讨论(0)
  • 2020-11-28 13:14

    Most of my reading agrees with Marcel, the ability to control thread if something goes (Abort ...) is something that should be heavily considered particularly if you are dealing with 3rd party calls over which you have no control and may hang.

    0 讨论(0)
提交回复
热议问题