Solved

Proper way to use C# Tasks?

Posted on 2016-09-06
4
27 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 32

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

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

705 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now