How to build for simultaneous tasks?
-
Wednesday, September 19, 2012 6:52 AM
I apologize if this is a vague question, but at this point, it's kind of a vague situation. As my signature shows, I'm still very much new to C#.
I'm trying to write a console program that will basically act as a chat bot. It will read the changes to the log file {at least until I figure out how to read data from it directly} and reacts accordingly.
Now, most of the tasks it would perform would be nearly instantaneous - just look up information and spit out a response. Some, on the other hand, would take a while.
For example, a command comes in to process and upload a locally archived forum thread. Depending on the size, both the processing and the upload can easily take several minutes, during which other instructions may come in. So basically, how would I go about essentially building the program with internal multitasking in mind? Are there articles or similar resources you'd recommend? I'm not sure how much code itself would help {other than as examples} since the question is more... conceptual, rather than practical.
C# newbie, learning on the go. I will probably ask a lot of followup questions about any answers already given, so fair warning and all.
All Replies
-
Wednesday, September 19, 2012 4:43 PMModerator
There are many options. The simplest would probably just be to assign operation as a "task" using the TPL, and fire it off when they come in. This will (by default) use the thread pool to schedule them.
For some details, see: http://reedcopsey.com/2010/03/15/parallelism-in-net-part-13-introducing-the-task-class/
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".- Proposed As Answer by Lisa ZhuMicrosoft Contingent Staff, Moderator Thursday, September 20, 2012 6:03 AM
-
Wednesday, September 19, 2012 6:41 PM
This looks like a decent starter blog for you:
http://www.codeproject.com/Articles/362996/Multi-core-programming-using-Task-Parallel-Library
Roar Jørstad Senior consultant http://www.evry.com
-
Wednesday, September 19, 2012 10:58 PMa book I bought isn't bad either : "Professional Parallel Programming with C#" by Gaston Hillar
-
Thursday, September 20, 2012 11:19 AM
And apparently, the word I was looking for is "threading". Ahh, the joys of being too newbish to speak the lingo.
At least I think it was. To all intents and purposes, a thread is essentially a process-within-a-process, correct? So for each response, I could assign a thread to the pool, right? And once the methods assigned to each response type are done, the thread is disposed of and not taking up resources any more, correct? For example;
using System; using System.Threading; public class Example { public static void Main() { for (int x = 0; x <= 100; x++) { ThreadPool.QueueUserWorkItem(new WaitCallback(test)); } Console.WriteLine("Main thread does some work, then sleeps."); while (Console.ReadKey().KeyChar != 'q') ; } static void test(Object stateInfo) { Console.WriteLine("Hello from the first thread pool."); Thread.Sleep(50); Console.WriteLine("Goodbye from the first thread pool."); } }
- would not leave any loose ends, correct?C# newbie, learning on the go. I will probably ask a lot of followup questions about any answers already given, so fair warning and all.
-
Thursday, September 20, 2012 3:38 PMModerator
And apparently, the word I was looking for is "threading". Ahh, the joys of being too newbish to speak the lingo.
At least I think it was. To all intents and purposes, a thread is essentially a process-within-a-process, correct? So for each response, I could assign a thread to the pool, right? And once the methods assigned to each response type are done, the thread is disposed of and not taking up resources any more, correct?
That's the right idea, for the most part. I wouldn't think of it as a "process within a process" as much as a way for one process to run multiple things at once.
The TPL, btw, provides a "nicer" way to use the ThreadPool. This is especially true if you want to return values from your methods that are running in separate threads. That's quite a bit more challenging when you use ThreadPool.QueueUserWorkItem - getting data out of the spawned delegate is tricky at best. With Task<T>, it's very easy.
Just as an FYI - your example, using the TPL, would look like:
using System; using System.Threading.Tasks; public class Example { public static void Main() { for (int x = 0; x <= 100; x++) { Task.Factory.StartNew(() => Test()); // Or just: Task.Factory.StartNew(Test); } Console.WriteLine("Main thread does some work, then sleeps."); while (Console.ReadKey().KeyChar != 'q') ; } static void Test() { Console.WriteLine("Hello from the first thread pool."); Thread.Sleep(50); Console.WriteLine("Goodbye from the first thread pool."); } }
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".- Marked As Answer by TheQuinch Friday, September 21, 2012 5:32 AM
-
Friday, September 21, 2012 5:34 AM
Gotcha, I'll poke around that. I'm guessing the difference betweenTask.Factory.StartNew(() => Test()); // Or just: Task.Factory.StartNew(Test);
- is that I can't pass arguments in the second approach? I still haven't gotten the time to get a hold on the lambda expressions, whatever they are exactly.C# newbie, learning on the go. I will probably ask a lot of followup questions about any answers already given, so fair warning and all.
-
Friday, September 21, 2012 6:00 AMOh, another question - how would I pause execution of a specific task without pausing all tasks? Using Thread.Sleep gives me... odd results.
C# newbie, learning on the go. I will probably ask a lot of followup questions about any answers already given, so fair warning and all.
-
Friday, September 21, 2012 3:50 PMModerator
As for your first question - yes, with the first approach, you can use a closure in the lambda to pass other arguments directly. The second just builds the delegate directly from the method (since the signature fits System.Action), but doesn't allow you to do anything else.
For your second question: There isn't a direct way to "pause" a Task. Typically, the best option is to not do this, but if you really want to, WaitHandles are the best option. ManualResetEvent, for example, lets you "wait" on something and trigger it from outside, etc. There are various options, but it depends on what you want to do.
In general, though, it's typically easiest to not try to "pause" a work in progress, but rather just let the task run, and use Task<T>.Result or Task.Wait() to wait on other tasks for composing. The main reason to pause is normally because you have to wait for another operation to finish - if you just call "Wait()" on that other task, it will block until it completes, without sleeping, etc.
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful". -
Friday, September 21, 2012 5:14 PMWell, yes and no. The main reason I need to put the task to wait is because I don't know when it's actually finished. Specifically, if I'm uploading a processed file, I don't know when the uploading is done {short explanation, Dropbox} so the only way I can think of checking if it's done is by periodically sending a HEAD request to see if it's finally there - so the wait would be repeated until a condition is satisfied.
C# newbie, learning on the go. I will probably ask a lot of followup questions about any answers already given, so fair warning and all.
-
Friday, September 21, 2012 6:37 PMModerator
Well, yes and no. The main reason I need to put the task to wait is because I don't know when it's actually finished. Specifically, if I'm uploading a processed file, I don't know when the uploading is done {short explanation, Dropbox} so the only way I can think of checking if it's done is by periodically sending a HEAD request to see if it's finally there - so the wait would be repeated until a condition is satisfied.
C# newbie, learning on the go. I will probably ask a lot of followup questions about any answers already given, so fair warning and all.
The mechanism you use to upload should tell you when it's done - UploadData, for example, won't return until it's complete. If you use the new async versions (ie: UploadDataTaskAsync), you can just use await on the result, and the code won't continue past until it's done uploading...
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful". -
Saturday, September 22, 2012 3:19 AM
Ideally, yes. In practice - what I'm using to host data is basically a cloud hosting/backup service that essentially synchronizes contents of a folder on my computer with a publicly accessible folder online {I think MS's SkyDrive works on the same principle?}. Thus, what I do is basically just copy the processed file into the "Public" folder and wait for it to finish synchronizing before providing a link.
It's a very, very far from ideal solution, but it's what I have to work with.
C# newbie, learning on the go. I will probably ask a lot of followup questions about any answers already given, so fair warning and all.

