How to call a method async with some kind of prior

2019-03-04 03:53发布

问题:

I need to call a couple of methods asynchronously with different priorities.

My first idea was to use the ThreadPool and change the priority of the Thread like this:

static void Run()
{
  ThreadPool.QueueUserWorkItem(new WaitCallback(SomeMethod));
}

static void SomeMethod(object o)
{
  Thread.CurrentThread.Priority = ThreadPriority.BelowNormal; // is this ok?
  // do some work here
}

Does that work or what do you recommend?

回答1:

According to http://msdn.microsoft.com/en-us/library/0ka9477y.aspx, it won't work if you are targeting 2.0, it alludes to there being some differences in 3.5 but doesn't specifically mention priority:

When Not to Use Thread Pool Threads

There are several scenarios in which it is appropriate to create and manage your own threads instead of using thread pool threads:

  • You require a foreground thread.

  • You require a thread to have a particular priority.

  • You have tasks that cause the thread to block for long periods of time. The thread pool has a maximum number of threads, so a large number of blocked thread pool threads might prevent tasks from starting.

  • You need to place threads into a single-threaded apartment. All ThreadPool threads are in the multithreaded apartment.

  • You need to have a stable identity associated with the thread, or to dedicate a thread to a task.

You'll likely need to come up with your own implementation, and handle creation of Threads directly.

Question: What are you trying to achieve do you have a set of tasks to be processed and you want high priority tasks to happen first, and lower ones to happen later; or do you actually want Threads of differing priority?



回答2:

That's definitely a horrible idea.

Generally speaking, setting a thread or process priority is a bad idea, because it is non deterministic, and you might starve out other threads/processes in the act. Also, you might actually elevate the priority of lower priority threads/processes because of starvation.

On top of that, the thread pool's threads are meant to be reused, and by changing the priority of the thread, you are changing the expectation of the task that will get the thread for use after your routine runs.

That being said, you have two options. If you only need to prioritize your tasks and don't mind if other items not related to your tasks get executed before yours, then you can use the thread pool with a producer consumer pattern, with some wrapper code which will take the highest priority item from your queue.

If you want the threads only to run your tasks, then you have to create your own thread pool (using the System.Thread class) and then do the same thing, using wrapper code to get the task to execute based on priority.

The new classes in the System.Threading namespace in .NET 4.0 (not released yet) will handle the creation of a separate thread pool for you.



回答3:

I think to be clean you should also restore the thread priority back when you get out of the method! (use try ... finally or something similar)



回答4:

here is a old but very detailed custom thread pool implementation supporting differing priorities.