First, could someone with 1500+ "reputation" please create a tag for "ContinueWith" (and tag this question with it)? Thanks!
Sorry for the length of this post but I don't want to waste the time of anyone trying to help me because I left out relevant details. That said, it may still happen. :)
Now the details. I am working on a service that subscribes to a couple of ActiveMQ queue topics. Two of the topics are somewhat related. One is a "company update" and one is a "product update". The "ID" for both is the CompanyID. The company topic includes the data in the product topic. Required because other subscribers need the product data but don't want/need to subscribe to the product topic. Since my service is multi-threaded (requirement beyond our discretion), as the messages arrive I add a Task to process each one in a ConcurrentDictionary using AddOrUpdate where the update parm is simply a ContinueWith (see below). Done to prevent simultaneous updates which could happen because these topics and subscribers are "durable" so if my listener service goes offline (whatever reason) we could end with multiple messages (company and/or product) for the same CompanyID.
Now, my actual question (finally!) After the Task (whether just one task, or the last in a chain of ContinueWith tasks) is finished, I want to remove it from the ConcurrentDictionary (obviously). How? I have thought of and gotten some ideas from coworkers but I don't really like any of them. I am not going to list the ideas because your answer might be one of those ideas I have but don't like but it may end up being the best one.
I have tried to compress the code snippet to prevent you from having to scroll up and down too much, unlike my description. :)
nrtq = Not Relevant To Question
public interface IMessage
{
long CompantId { get; set; }
void Process();
}
public class CompanyMessage : IMessage
{ //implementation, nrtq }
public class ProductMessage : IMessage
{ //implementation, nrtq }
public class Controller
{
private static ConcurrentDictionary<long, Task> _workers = new ConcurrentDictionary<long, Task>();
//other needed declarations, nrtq
public Controller(){//constructor stuff, nrtq }
public StartSubscribers()
{
//other code, nrtq
_companySubscriber.OnMessageReceived += HandleCompanyMsg;
_productSubscriber.OnMessageReceived += HandleProductMsg;
}
private void HandleCompanyMsg(string msg)
{
try {
//other code, nrtq
QueueItUp(new CompanyMessage(message));
} catch (Exception ex) { //other code, nrtq }
}
private void HandleProductMsg(string msg)
{
try {
//other code, nrtq
QueueItUp(new ProductMessage(message));
} catch (Exception ex) { //other code, nrtq }
}
private static void QueueItUp(IMessage message)
{
_workers.AddOrUpdate(message.CompanyId,
x => {
var task = new Task(message.Process);
task.Start();
return task;
},
(x, y) => y.ContinueWith((z) => message.Process())
);
}
Thanks!