 <p>Perhaps, one way that I can think of is </p> <ol> <li>Create a wrapper class - say KeyProcessor to queue up items for a key. </li> <li>KeyProcessor.Run() method will be capable of whatever queuing semantics that you need for. Essentially it would look for internal queue for any pending work and then keep doing it sequentially.</li> <li>Maintain the dictionary of KeyProcessor objects.</li> <li>For any new task, check in the dictionary for the same key. If does not exist then add it. Queue the task on it. If its not running then schedule it with TPL using Run method as action.</li> <li>Use ContinueWith to schedule maintainer task - for example, whenever Task executing KeyProcessor.Run is completed, continuation tasks can check if there are any more tasks been scheduled for the same key (since it has completed) and start it again OR remove from dictionary.</li> </ol> <p>All above would have been tricky from thread sync point not for few interesting collections present in <a href="http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx" rel="nofollow noreferrer">System.Collections.Concurrent</a> namespace. This would make the above logic much more simpler. For example, <a href="http://msdn.microsoft.com/en-us/library/ee378677.aspx" rel="nofollow noreferrer">ConcurrentDictionary.GetOrAdd </a> will allow to lookup and/or add the KeyProcessor object in thread-safe way.</p>