每个循环的并行内部顺序执行

时间:2012-03-07 18:26:49

标签: c# .net parallel-processing

我的要求是这样的。我很少有独立的工作和很少的顺序工作,遵守合同。在我的客户端应用程序中,在Parallel For循环中,我需要确保独立任务以任何顺序执行,但如果它们是顺序的,它们应该是一个接一个。下面是我的代码。谢谢,

 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

这是独立的工作 第1步:从XML获取数据 第2步:转储XML格式的数据 这是独立的工作 按任意键继续 。 。

我可以这样做吗

      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());

2 个答案:

答案 0 :(得分:3)

对于所有顺序任务,您应该只有一个IContract。该合同的执行方法应该调用所有需要按顺序运行的2,3等方法。如果你有另外一组2个任务要按顺序运行,那将是另一个IContract。您不应为一组应按顺序运行的任务定义多个IContract。如果您不想这样做,则需要重新设计整个框架以引入依赖关系或更多涉及的内容。

答案 1 :(得分:0)

您的根本问题是,您无法使用反射确定XMLJobDumpToDBJob应该是序列的一部分。您可以使用自定义属性进行设置。

正如Servy所指出的,对于每组顺序任务,您只能将第一个任务放入并行列表中,并让序列中的每个任务都开始其后继任务。使用反射启动批次时,在这种方法下,您需要有一些方法来避免启动DumpToDBJob(因为它将作为XMLJob的最后一个操作启动。)

或者,您可以创建一个按顺序执行一系列任务的包装器任务,并将那个放在列表中。

例如:

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();
    }
}

如果您手动创建此类的实例,则可以调用new SequentialJob(new XMLJob(), new DumpToDBJob())。但同样,如果你正在使用反射,你需要某种方法来识别传递给这个作业的构造函数的正确对象,以及它的顺序。