Reputation: 1375
My requirement is some thing like this. I have few independent jobs and few sequential jobs which abide to a contract. In my client app, inside Parallel For loop I need to make to sure the independent tasks get executed in any order but if they sequential they should be one after another. below is my code. Thanks,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Threading.Tasks;
namespace Sample
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
List<IContract> list = p.Run();
Parallel.ForEach(list, t=> t.Execute());
}
List<IContract> Run()
{
List<IContract> list = new List<IContract>();
Type[] typesInThisAssembly = Assembly.GetExecutingAssembly().GetTypes();
Array.ForEach(
typesInThisAssembly,
type =>
{
// If the type of this interface is not IChartView, continue the loop
if (type.GetInterface(typeof(IContract).ToString()) != null)
{
var contractObj = Activator.CreateInstance(type, new object[] { }) as IContract;
list.Add(contractObj);
}
});
return list;
}
}
public interface IContract
{
void Execute();
}
public class XMLJob : IContract
{
public void Execute()
{
Console.WriteLine("Step1: Getting data from XML");
}
}
public class DumpToDBJob : IContract
{
public void Execute()
{
Console.WriteLine("Step2: Dumping Data whihc came in XML");
}
}
public class IndependentJob1 : IContract
{
public void Execute()
{
Console.WriteLine("This is independent Job");
}
}
public class IndependentJob2 : IContract
{
public void Execute()
{
Console.WriteLine("This is independent Job ");
}
}
}
Desire Out Put
This is independent Job Step1: Getting data from XML Step2: Dumping Data whihc came in XML This is independent Job Press any key to continue . . .
Can I do like this
Program p = new Program();
List<IContract> list = p.Run();
IContract xj = list.Find(i => i.GetType().ToString() == typeof(XMLJob).ToString());
IContract dj = list.Find(i => i.GetType().ToString() == typeof(DumpToDBJob).ToString());
list.Remove(xj);
list.Remove(dj);
Parallel.ForEach(list, l => l.Execute());
List<Task> tasks = new List<Task>();
Task t1 = Task.Factory.StartNew(xj.Execute);
Task t2 = t1.ContinueWith((antecedent)=>dj.Execute());
tasks.Add(t1);
tasks.Add(t2);
Task.WaitAll(tasks.ToArray());
Upvotes: 0
Views: 1873
Reputation: 43036
Your underlying problem is that you have no way to determine, using reflection, that XMLJob
and DumpToDBJob
should be part of a sequence. You might set that up using custom attributes.
As Servy noted, for each set of sequential tasks, you could put only the first one in the parallel list, and have each task in the sequence start its successor. When starting the lot using reflection, under this approach, you'd need to have some way to avoid starting DumpToDBJob
(because it will be started as the last action of XMLJob
).
Alternatively, you could make a wrapper task that executes a sequence of tasks in order, and put that in the list.
For example:
public class SequentialJob : IContract
{
private readonly IEnumerable<IContract> _children;
public SequentialJob(params IContract[] children)
{
_children = children;
}
public void Execute()
{
foreach (var child in children)
child.Execute();
}
}
If you were creating an instance of this class manually, you could call new SequentialJob(new XMLJob(), new DumpToDBJob())
. But again, if you're using reflection, you'd need some way of identifying the correct objects to pass to this job's constructor, and in what order.
Upvotes: 0
Reputation: 203814
For all of the sequential tasks you should only have a single IContract
. The execute method of that contract should call the 2, 3, etc. methods that all need to be run sequentially. If you have another group of 2 tasks to be run sequentially that would be another IContract
. You should not have more than one IContract
s defined for a group of tasks that should be run in sequence. If you don't want to do it that way you'll need to re-design your entire framework to introduce dependencies or something more involved.
Upvotes: 3