I have a simple Employee class as follows
public class Employee
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
}
I then have a ProcessEmployees class which do concurrent processing of these employees in method called ProcessThisEmployee. Within this method, I have to call a third party library method. So far its all simple. Problem is sometime when user choose to cancel this operation when its in progress, I need to do some clean up on any ThirdPartyLibrary class instances that haven't completed processing yet. Note I don't have any control on the ThirdPartyLibrary class and it does not have any mechanism for cancellation an existing task. It does provide a Clean method that I can call on any instances where call to SomeAPI hasn't finished yet. As a result, I am maintaining an local List of all instances. When user choose to cancel operation, I call CleaupIfUserCancelOperation method of my class that Clean method of this third party library instance that are in the my local list. Below is my code for this.
class ProcessEmployees
{
private List<Employee> _Employees;
List<ThirdPartyLibrary> libraries = new List<ThirdPartyLibrary>();
private object sync = new object();
public ProcessEmployees()
{
_Employees = new List<Employee>()
{
new Employee() { ID = 1, FirstName = "John", LastName = "Doe" },
new Employee() { ID = 2, FirstName = "Peter", LastName = "Saul" },
new Employee() { ID = 3, FirstName = "Mike", LastName = "Sue" },
new Employee() { ID = 4, FirstName = "Catherina", LastName = "Desoza" },
new Employee() { ID = 5, FirstName = "Paul", LastName = "Smith" }
};
}
public void StartProcessing()
{
Task[] tasks = this._Employees.AsParallel().Select(x => this.ProcessThisEmployee(x)).ToArray();
Task.WaitAll(tasks);
// other stuff
}
private async Task ProcessThisEmployee(Employee x)
{
ThirdPartyLibrary library = new ThirdPartyLibrary();
lock (sync)
{
libraries.Add(library);
}
await Task.Factory.StartNew(() => library.SomeAPI(x) );
lock (sync)
{
libraries.Remove(library);
}
}
private void CleaupIfUserCancelOperation()
{
foreach (ThirdPartyLibrary library in libraries)
library.Clean();
}
}
I have to lock libraries instance twice in here which of course is a performance hit. Can there be any lightweight (lock-free) mechanism that could be used in this case? I don't know much about the concurrent collection, wonder if those could be of any use in this scenario?