简体   繁体   中英

How can I ensure two tasks are running on different threads or even different processors with the new Task Parallel Library?

I have two long running tasks that read and write simultaneously from a network stream which requires me to use two different threads.
I have marked them as long running but according to the docs marking them as long running only recommends but doesn't guarantee that they will run on different threads.
Do I need to write my own Task Scheduler? Should I use the thread pool instead?

LongRunning is a hint that it should be executed on a new Thread, instead of an existing thread in the ThreadPool. This is so you wont exhaust the ThreadPool with long-running tasks.

There are no guarantees that two different threads will be used, neither in TPL, nor with the ThreadPool. For example, it could be the same thread executing both tasks synchronously.

Have you looked into using asynchronous io instead?

If "network stream" means the NetworkStream class, I'm not sure why you really need two separate threads here. Are you basing that on the following quote from the documentation:

"As long as there is one unique thread for the write operations and one unique thread for the read operations, there will be no cross-interference between read and write threads and no synchronization is required"

If so, that's only a suggestion - they're saying that if you do things this way, you don't need to do any synchronization. The main reason they're saying this is that NetworkStream is unusual in that it supports access from two threads simultaneously as long as one is reading and one is writing.

But it's clear from the documentation that you also have the option to perform synchronization - they're just saying that synchronization is unnecessary if you choose to go down the path of having exactly one read thread, and exactly one write thread.

But if for some reason you really do need two dedicated threads, then...I'd just use the Thread class. Trying to get Task to do that for you (either directly, or indirectly via a TaskScheduler ) is probably just making things more complex. This doesn't prevent you from using the TPL - you could use the TaskCompletionSource to create tasks, and finish them at your own leisure. (TCS is the normal solution for situations where you want to control how tasks execute, but still expose them as a Task object.)

string[] forums = File.ReadAllLines(Environment.CurrentDirectory + @"\forums.txt");

Task[] tasks = new Task[forums.Length ];
int ctr = 0;
DateTime Start = DateTime.Now;`
foreach(string s in forums)`
{
object state = s;
var task = Task.Factory.StartNew(() => DoSomeWork(state),TaskCreationOptions.LongRunning);
tasks[ctr] = task;
ctr++;
}

Task.WaitAll(tasks);
DateTime end = DateTime.Now;
TimeSpan elapsed = end - Start;
string totalMs = elapsed.TotalMilliseconds.ToString();
Console.WriteLine("DONE in " +totalMs + " ms. Any Key to quit.");
Console.ReadKey();

LongRunning枚举方法重载告诉任务库为每个任务分配一个线程,而不管它可以使用多少核。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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