It's often the case when I need to get a task done within X amount of seconds and if it doesn't complete, I want to keep going, processing the rest of the tasks
I've been defaulting to something like this:
Thread worker = new Thread(() => {
// do some long operation
});
Thread monitor = new Thread(() => {
Thread.Sleep(10000);
if(worker != null && worker.IsAlive) {
worker.Abort();
worker = null;
}
StartNextTask();
});
monitor.Start ();
worker.Start();
This works, but it is cumbersome because it uses two threads (yes, you can use the Task class as well to use threads from the threadpool).
AutoResetEvents and event based models don't quite work because the former blocks the monitor thread until the worker is done, and the event driven approach relies on the client to call the event and notify the monitor.
Are there alternative patterns to this that can follow the same semantics?
If you use the Task class as you say, you can also use Task.Wait() which does exactly what you want. Specify an amount of seconds to wait. The task doesn't get cancelled unless you cancel it by use of a CancellationToken
See: http://msdn.microsoft.com/en-us/library/dd235606.aspx
Related
I am new to threaded programming. I have to run few tasks in PARALLEL and in Background (so that main UI execution thread remain responsive to user actions) and wait for each one of them to complete before proceeding further execution.
Something like:
foreach(MyTask t in myTasks)
{
t.DoSomethinginBackground(); // There could be n number of task, to save
// processing time I wish to run each of them
// in parallel
}
// Wait till all tasks complete doing something parallel in background
Console.Write("All tasks Completed. Now we can do further processing");
I understand that there could be several ways to achieve this. But I am looking for the best solution to implement in .Net 4.0 (C#).
To me it would seem like you want Parallel.ForEach
Parallel.ForEach(myTasks, t => t.DoSomethingInBackground());
Console.Write("All tasks Completed. Now we can do further processing");
You can also perform multiple tasks within a single loop
List<string> results = new List<string>(myTasks.Count);
Parallel.ForEach(myTasks, t =>
{
string result = t.DoSomethingInBackground();
lock (results)
{ // lock the list to avoid race conditions
results.Add(result);
}
});
In order for the main UI thread to remain responsive, you will want to use a BackgroundWorker and subscribe to its DoWork and RunWorkerCompleted events and then call
worker.RunWorkerAsync();
worker.RunWorkerAsync(argument); // argument is an object
You can use Task library to complete:
string[] urls = ...;
var tasks = urls.Select(url => Task.Factory.StartNew(() => DoSomething(url)));
To avoid locking UI Thread, you can use ContinueWhenAll in .NET 4.0:
Task.Factory.ContinueWhenAll(tasks.ToArray(), _ =>
Console.Write("All tasks Completed. Now we can do further processing");
);
If you are in the latest version of .NET, you can use Task.WhenAll instead
If you use Net 4.0 or up, refer to the Parallel class and Task class. Joseph Albahari wrote very clear book about that: http://www.albahari.com/threading/part5.aspx#_Creating_and_Starting_Tasks
I am a software/hardware engineer with quite some experience in C and embedded technologies. Currently i am busy with writing some applications in C# (.NET) that is using hardware for data acquisition. Now the following, for me burning, question:
For example: I have a machine that has an endswitch for detecting the final position of an axis. Now i am using a USB Data acquisition module to read the data. Currently I am using a Thread to continuously read the port-status.
There is no interrupt functionality on this device.
My question: Is this the right way? Should i use timers, threads or Tasks? I know polling is something that most of you guys "hate", but any suggestion is welcome!
IMO, this heavily depends on your exact environment, but first off - You should not use Threads anymore in most cases. Tasks are the more convenient and more powerful solution for that.
Low polling frequency: Timer + polling in the Tick event:
A timer is easy to handle and stop. No need to worry about threads/tasks running in the background, but the handling happens in the main thread
Medium polling frequency: Task + await Task.Delay(delay):
await Task.Delay(delay) does not block a thread-pool thread, but because of the context switching the minimum delay is ~15ms
High polling frequency: Task + Thread.Sleep(delay)
usable at 1ms delays - we actually do this to poll our USB measurement device
This could be implemented as follows:
int delay = 1;
var cancellationTokenSource = new CancellationTokenSource();
var token = cancellationTokenSource.Token;
var listener = Task.Factory.StartNew(() =>
{
while (true)
{
// poll hardware
Thread.Sleep(delay);
if (token.IsCancellationRequested)
break;
}
// cleanup, e.g. close connection
}, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
In most cases you can just use Task.Run(() => DoWork(), token), but there is no overload to supply the TaskCreationOptions.LongRunning option which tells the task-scheduler to not use a normal thread-pool thread.
But as you see Tasks are easier to handle (and awaitable, but does not apply here). Especially the "stopping" is just calling cancellationTokenSource.Cancel() in this implementation from anywhere in the code.
You can even share this token in multiple actions and stop them at once. Also, not yet started tasks are not started when the token is cancelled.
You can also attach another action to a task to run after one task:
listener.ContinueWith(t => ShutDown(t));
This is then executed after the listener completes and you can do cleanup (t.Exception contains the exception of the tasks action if it was not successful).
IMO polling cannot be avoided.
What you can do is create a module, with its independent thread/Task that will poll the port regularly. Based on the change in data, this module will raise the event which will be handled by the consuming applications
May be:
public async Task Poll(Func<bool> condition, TimeSpan timeout, string message = null)
{
// https://github.com/dotnet/corefx/blob/3b24c535852d19274362ad3dbc75e932b7d41766/src/Common/src/CoreLib/System/Threading/ReaderWriterLockSlim.cs#L233
var timeoutTracker = new TimeoutTracker(timeout);
while (!condition())
{
await Task.Yield();
if (timeoutTracker.IsExpired)
{
if (message != null) throw new TimeoutException(message);
else throw new TimeoutException();
}
}
}
Look into SpinWait or into Task.Delay internals either.
I've been thinking about this and what you could probably do is build an abstraction layer on utilizing Tasks and Func, Action with the Polling service taking in the Func, Action and polling interval as args. This would keep the implementation of either functionality separate while having them open to injection into the polling service.
So for example you'd have something like this serve as your polling class
public class PollingService {
public void Poll(Func<bool> func, int interval, string exceptionMessage) {
while(func.Invoke()){
Task.Delay(interval)
}
throw new PollingException(exceptionMessage)
}
public void Poll(Func<bool, T> func, T arg, int interval, string exceptionMessage)
{
while(func.Invoke(arg)){
Task.Delay(interval)
}
throw new PollingException(exceptionMessage)
}
}
I want to queue dependant tasks across several flows that need to be processed in order (in each flow). The flows can be processed in parallel.
To be specific, let's say I need two queues and I want the tasks in each queue to be processed in order. Here is sample pseudocode to illustrate the desired behavior:
Queue1_WorkItem wi1a=...;
enqueue wi1a;
... time passes ...
Queue1_WorkItem wi1b=...;
enqueue wi1b; // This must be processed after processing of item wi1a is complete
... time passes ...
Queue2_WorkItem wi2a=...;
enqueue wi2a; // This can be processed concurrently with the wi1a/wi1b
... time passes ...
Queue1_WorkItem wi1c=...;
enqueue wi1c; // This must be processed after processing of item wi1b is complete
Here is a diagram with arrows illustrating dependencies between work items:
The question is how do I do this using C# 4.0/.NET 4.0? Right now I have two worker threads, one per queue and I use a BlockingCollection<> for each queue. I would like to instead leverage the .NET thread pool and have worker threads process items concurrently (across flows), but serially within a flow. In other words I would like to be able to indicate that for example wi1b depends on completion of wi1a, without having to track completion and remember wi1a, when wi1b arrives. In other words, I just want to say, "I want to submit a work item for queue1, which is to be processed serially with other items I have already submitted for queue1, but possibly in parallel with work items submitted to other queues".
I hope this description made sense. If not please feel free to ask questions in the comments and I will update this question accordingly.
Thanks for reading.
Update:
To summarize "flawed" solutions so far, here are the solutions from the answers section that I cannot use and the reason(s) why I cannot use them:
TPL tasks require specifying the antecedent task for a ContinueWith(). I do not want to maintain knowledge of each queue's antecedent task when submitting a new task.
TDF ActionBlocks looked promising, but it would appear that items posted to an ActionBlock are processed in parallel. I need for the items for a particular queue to be processed serially.
Update 2:
RE: ActionBlocks
It would appear that setting the MaxDegreeOfParallelism option to one prevents parallel processing of work items submitted to a single ActionBlock. Therefore it seems that having an ActionBlock per queue solves my problem with the only disadvantage being that this requires the installation and deployment of the TDF library from Microsoft and I was hoping for a pure .NET 4.0 solution. So far, this is the candidate accepted answer, unless someone can figure out a way to do this with a pure .NET 4.0 solution that doesn't degenerate to a worker thread per queue (which I am already using).
I understand you have many queues and don't want to tie up threads. You could have an ActionBlock per queue. The ActionBlock automates most of what you need: It processes work items serially, and only starts a Task when work is pending. When no work is pending, no Task/Thread is blocked.
The best way is to use the Task Parallel Library (TPL) and Continuations. A continuation not only allows you to create a flow of tasks but also handles your exceptions. This is a great introduction to the TPL. But to give you some idea...
You can start a TPL task using
Task task = Task.Factory.StartNew(() =>
{
// Do some work here...
});
Now to start a second task when an antecedent task finishes (in error or successfully) you can use the ContinueWith method
Task task1 = Task.Factory.StartNew(() => Console.WriteLine("Antecedant Task"));
Task task2 = task1.ContinueWith(antTask => Console.WriteLine("Continuation..."));
So as soon as task1 completes, fails or is cancelled task2 'fires-up' and starts running. Note that if task1 had completed before reaching the second line of code task2 would be scheduled to execute immediately. The antTask argument passed to the second lambda is a reference to the antecedent task. See this link for more detailed examples...
You can also pass continuations results from the antecedent task
Task.Factory.StartNew<int>(() => 1)
.ContinueWith(antTask => antTask.Result * 4)
.ContinueWith(antTask => antTask.Result * 4)
.ContinueWith(antTask =>Console.WriteLine(antTask.Result * 4)); // Prints 64.
Note. Be sure to read up on exception handling in the first link provided as this can lead a newcomer to TPL astray.
One last thing to look at in particular for what you want is child tasks. Child tasks are those which are created as AttachedToParent. In this case the continuation will not run until all child tasks have completed
TaskCreationOptions atp = TaskCreationOptions.AttachedToParent;
Task.Factory.StartNew(() =>
{
Task.Factory.StartNew(() => { SomeMethod() }, atp);
Task.Factory.StartNew(() => { SomeOtherMethod() }, atp);
}).ContinueWith( cont => { Console.WriteLine("Finished!") });
I hope this helps.
Edit: Have you had a look at ConcurrentCollections in particular the BlockngCollection<T>. So in your case you might use something like
public class TaskQueue : IDisposable
{
BlockingCollection<Action> taskX = new BlockingCollection<Action>();
public TaskQueue(int taskCount)
{
// Create and start new Task for each consumer.
for (int i = 0; i < taskCount; i++)
Task.Factory.StartNew(Consumer);
}
public void Dispose() { taskX.CompleteAdding(); }
public void EnqueueTask (Action action) { taskX.Add(Action); }
void Consumer()
{
// This seq. that we are enumerating will BLOCK when no elements
// are avalible and will end when CompleteAdding is called.
foreach (Action action in taskX.GetConsumingEnumerable())
action(); // Perform your task.
}
}
A .NET 4.0 solution based on TPL is possible, while hiding away the fact that it needs to store the parent task somewhere. For example:
class QueuePool
{
private readonly Task[] _queues;
public QueuePool(int queueCount)
{ _queues = new Task[queueCount]; }
public void Enqueue(int queueIndex, Action action)
{
lock (_queues)
{
var parent = _queue[queueIndex];
if (parent == null)
_queues[queueIndex] = Task.Factory.StartNew(action);
else
_queues[queueIndex] = parent.ContinueWith(_ => action());
}
}
}
This is using a single lock for all queues, to illustrate the idea. In production code, however, I would use a lock per queue to reduce contention.
It looks like the design you already have is good and working. Your worker threads (one per queue) are long-running so if you want to use Task's instead, specify TaskCreationOptions.LongRunning so you get a dedicated worker thread.
But there isn't really a need to use the ThreadPool here. It doesn't offer many benefits for long-running work.
I am a bit new to threading as I have never needed it on an advanced level up until now.
I have the following problem I need to solve:
I have an application where you specify how many threads it should work with, and after that you get it to start.
I know this can be done with ThreadPool but I need a bit more functionality, I don't know how to make it so it makes a callback when all the threads are done and a function to stop all threads and queues if needed.
One idea was making a new thread and working with the threadpool from there so that when I kill that threat it kills are the ones started from that thread (being the main). Also that way I'd be able to set it to call back (the single thread) when the queue is cleared.
You could use Tasks and CancellationTokens:
var taskCount = 10;
var cancellationTokenSource = new CancellationTokenSource();
for (int i = 0; i < taskCount ; i++)
{
var cancellationToken = cancellationTokenSource.Token;
Task.Factory.StartNew(() =>
{
// do work here.
// Also periodically check
if( cancellationToken.IsCancellationRequested )
return;
// or wait on wait handle
cancellationToken.WaitHandle.WaitOne(timeout);
}, cancellationToken);
}
// to cancel all threads
cancellationTokenSource.Cancel();
The number of threads running concurrently is managed for you by the ThreadPool within the TaskFactory, based on your machine's reported CPU cores. If you want more control, it is possible to provide your own custom TaskFactories I believe.
I have a c# console application which has some threads to do some work (download a file).
each thread may exit the application at any time any where in application, but I'll show a proper message on console. It's possible to track them but it doesn't make sense to me. I want simply check thread count or something like that to find out which one is the last thread and do something when it is exiting.
What's the best practice to do so ?
pseudo code:
if (lastThread)
{
cleanUp();
Console.ReadLine();
}
Thanks
This is one place where using the new Task Parallel Library can make life much easier. Instead of creating threads, and spinning work up on the thread, you can use multiple tasks:
var task1 = Task.Factory.StartNew( () => DoTaskOneWork() );
var task2 = Task.Factory.StartNew( () => DoTaskTwoWork() );
var task3 = Task.Factory.StartNew( () => DoTaskThreeWork() );
// Block until all tasks are done
Task.WaitAll(new[] {task1, task2, task3} );
cleanUp(); // Do your cleanup
If the "tasks" are just downloading a bunch of individual files, you could even make this simpler using PLINQ:
var fileUrls = GetListOfUrlsToDownload();
fileUrls.AsParallel().ForAll( fileUrl => DownloadAndProcessFile(fileUrl) );
cleanUp(); // Do your cleanup
A design where you lose track of your threads is not ideal.
Depending on how you spawn them it ought to be possible to track the status of each by associating some per-thread signalable object, then WaitAll on those signalable objects.
Each signalable object in turn should get signaled as its thread exits. When they are all signaled, you know the threads are all dead and you close down clean. You have to make sure that abnormal conditions in your threads do not result in that thread's associated signalable object remaining unset, or your WaitAll will never return. This means exceptions typically - could use try...finally to ensure the objects get signaled.
Your new pseudocode is
foreach (workitem in list of work)
start up thread associated with a ManualResetEvent or similar
WaitAll for all events to be signalled
cleanup
Your main thread should join with all your worker threads and block while they are running. Then when all threads are complete it performs the cleanup code and then quits.
Alternatively you can use a WaitHandle such as as a ManualResetEvent per thread and wait for all of them to be signalled.