Solved

Proper way to use C# Tasks?

Posted on 2016-09-06
4
55 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
4 Comments
 
LVL 34

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 23

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

Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
asp.net figure out error 3 47
PowerShell: Adding ToGB to a script 4 74
Load XML element 3 43
Help with viewing image in ReportViewer 14 31
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…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

751 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