Solved

Proper way to use C# Tasks?

Posted on 2016-09-06
4
50 Views
Last Modified: 2016-10-23
Hi,

I am trying to get clarification on how to use C# Tasks.

Lets say I have 10,000 objects I want to process.

Is it sensible to create 10,000 Task objects with the Task.Factory?

https://msdn.microsoft.com/en-us/library/dd321439(v=vs.110).aspx
TaskFactory.StartNew Method (Action)

Or should I be tiring to re-use a limited number?

However from the doco I am not sure how to do this. (Sure it something I have missed).

I have had some problems with things in the WaitingToRun state for longer then I would of expected.

So I am hoping to get some general guidance on all of this. (And some examples if possible).

Thanks,
0
Comment
Question by:whorsfall
4 Comments
 
LVL 33

Accepted Solution

by:
ste5an earned 250 total points
ID: 41786119
It depends on the kind of tasks to perform and your machine, where you run those 10k tasks.

But generally speaking: No, its normally not a good idea.

Most for the reason that you may run you program on different machines, on capable of running only 50 tasks and another of running 500 tasks.

The normal approaches I use in such cases:

1) Use a blocking queue to store the task description. Use a single thread to spawn new threads when new task descriptions arrive and fewer then the maximum worker threads are alive.

Advantage: Each thread and its description are isolated from each other. State of threads does not matter.
Disadvantage: Needs some more time to instantiate.

Usage: When isolation is more important than speed. Like high-level jobs as print or download jobs.

2) Use a blocking queue to store the task description. Create a configurable amount of tasks. Each task takes its task description from the queue. When no more description is available, the tasks quits.

Advantage: Lesser time to instantiate.
Disadvantage: Threads keep state.
Usage: Low-level jobs like object processing for drawing graphics.

And then try to find a good number for your worker threads. E.g. for download tasks the bandwidth of your server is the bottleneck. Here even 100 or lesser tasks are optimal to balance memory and CPU consumption due to low bandwidth waits. Make this a configuration parameter in your app.config.
0
 

Author Comment

by:whorsfall
ID: 41786170
Hi ste5an,

Thanks for your response. Unless I am mistaken is there not some parameter you can get from the threadpool that says how many tasks you can run and the same time. And if you run more it block you?

ThreadPool.GetMaxThreads Method (Int32, Int32) --> Should I be looking at this figure ?

Also I have got some of my code below.

Is this kind of the right way. the function fnCreate3 deques data from the fake_pc_queue.


Thanks,

Ward

        private void fnRun_Queue(BlockingCollection<Fake_PC> processing_list,
                                 BlockingCollection<Fake_PC> fake_pc_results,
                                 BlockingCollection<Fake_PC> pc_error_list,
                                 Task_Stats my_stats,
                                 int number_of_threads,
                                 int iteration_count)
        {
            ConcurrentQueue<Fake_PC> fake_pc_queue = new ConcurrentQueue<Fake_PC>();
            int total_machines = processing_list.Count;
            int queue_count = 0;
            int results_count = 0;
            int error_count = 0;
            Task[] taskArray = null;
            string duration = null;

            DateTime start_time = DateTime.Now;

            fnUpdate_Status(string.Format("Starting iteration: {0} Records: {1}", iteration_count, processing_list.Count));
            Thread.Sleep(3000);

            foreach (Fake_PC my_pc in processing_list)
            {
                fake_pc_queue.Enqueue(my_pc);
            }

            Boolean execution_flag = true;

            int counter = 1;


            while (execution_flag == true)
            {

                // Task my_task = Task.Factory.StartNew(() => fnGet_Record_count());

                if (queue_count > 0)
                {
                    taskArray = new Task[number_of_threads];

                    for (int i = 0; i < number_of_threads; i++)
                    {

                            if (taskArray[i] == null || taskArray[i].Status == TaskStatus.RanToCompletion)
                            {
                                taskArray[i] = Task.Factory.StartNew(() => { return fnCreate3(fake_pc_queue, fake_pc_results, pc_error_list); });
                            }

                    }


                }
                else
                {
                    fnUpdate_Status("Waiting on threads to finish.");
                    Thread.Sleep(2000);
                }

                Task.WaitAny(taskArray);

            while (fake_pc_queue.IsEmpty == false)
            {
                Fake_PC my_pc;

                if (fake_pc_queue.TryDequeue(out my_pc))
                {
                    pc_error_list.Add(my_pc);
                }
            }

            fnUpdate_Task_Status("");
        }

Open in new window

0
 
LVL 22

Assisted Solution

by:Snarf0001
Snarf0001 earned 250 total points
ID: 41786590
Are you actually calling the same code for each object?  Obviously just sample data you provided.

If so, any reason not to just use Parallel.For (or .ForEach)?

You don't have as much lower level control, but does a very good job (in my experience) managing the different threads and tasks and splitting them out as needed across processors.

And is dirt simple to implement, with far less code.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Name Space error VS2015 1 35
Get month and date in a format 4 44
Visual Studio hangs on running project 6 55
Amazon S3 .Net error 5 36
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display

680 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question