1

我正在尝试模拟血流。尽可能简单,我试图让一个事件(TimerTick)触发资源对象从单元 A 到单元 B、B 到 C、C 到 A 的传输。我似乎无法从一个迭代到另一个迭代,我尝试了比下面粘贴的更多不同的方法。单元在施工后连接为三角形。我知道这会使第一个单元出错,并且尝试了多种方法来处理它(我不确定这是否是唯一的问题)但由于没有一个有效,我不会发布它们。任何一个单位都不需要了解任何其他单位的活动设置想法将不胜感激。但只是一种使这项工作的方法也将受到赞赏。

class Unit{    
Resource currentResource;
Resource incomingResource;
Unit preUnit;
Unit postUnit;
public Unit( int resource, Timer t)
    {
        this.currentResource = new Resource(resource);
        t.TimerTick += T_TimerTick;
    }
 private void T_TimerTick(object sender, TimerTickEventArgs e)
    {
        postUnit.receiveResource(currentResource);
        currentResource = incomingResource;
}
void receiveResource(Resource resource)
    {
        incomingResource = resource;
    }
//pre and post units connected appropriately to Cycle ...-A-B-C-A-...
// with one cycle per TimerTick
}
4

2 回答 2

0

这些元素和方法是否在一个名为 Unit 的类中命名为 Unit?

尝试将方法和元素移动到另一个类。

我会为您的单位制作三个静态类:

public static class UnitA
{
    var foo1;
    var foo2;
}

public static class UnitB
{
    var foo1;
    var foo2;
}

public static class UnitC
{
    var foo1;
    var foo2;
}

对于每个 tic,您可以处理来自任何其他类的资源:

FooHandler_Tick
{
    // Store C's content.
    var tempFoo1 = UnitC.foo1;
    var tempFoo2 = UnitC.foo2;

    // B to C.
    UnitC.foo1 = UnitB.foo1;
    UnitC.foo2 = UnitB.foo2;

    // A to B.
    UnitB.foo1 = UnitA.foo1;
    UnitB.foo2 = UnitA.foo2;

    // C to A.
    UnitC.foo1 = tempFoo1;
    UnitC.foo2 = tempFoo2;
}

这适用于您的项目吗?

于 2015-10-24T07:03:25.737 回答
0

我建议使用观察者模式进行控制反转

这是一个工作设置,用于解释我的建议。在我的代码中,每个单元只是将资源增加 1。

并产生以下输出

*启动单元 A 值 1

单元 A,输出 1

单元 B,输入 1

单元 B,输出 2

单元 C,输入 2

单元 C,输出 3

单元 A,输入 3

单元 A,循环完成*

客户代码

      IInitiatorUnit A = new InitiatorUnit("A");
        IUnit B = new Unit("B");
        IUnit C = new Unit("C");

        B.RegisterUnit(A); // B is listening to A
        C.RegisterUnit(B); // C is listening to B
        A.RegisterUnit(C); //  A is listinig to C


 void heartBeatTimer_Tick(object sender, EventArgs e)
    {
        A.GenerateResource(1); // Start the process
    }

我设计了一个单元,它接受一个输入,处理它并触发一个事件

     interface IUnit
    {
        event EventHandler<ResourceGeneratedEventArgs> ResourceGenerated;
        void RegisterUnit(IUnit inputUnit);
        string Name { get; }
    }

    class Unit : IUnit
    {

        IUnit mInputUnit;
        public event EventHandler<ResourceGeneratedEventArgs> ResourceGenerated;
        public string Name { get; private set; }

        public Unit(string name)
        {
            this.Name = name;
        }

        public void RegisterUnit(IUnit inputUnit)
        {
            this.mInputUnit = inputUnit;
            this.mInputUnit.ResourceGenerated += mInputUnitResourceGenrated;
        }

        void mInputUnitResourceGenrated(object sender, ResourceGeneratedEventArgs inputResource)
        {
           //take the input resorce. pocess it & fire the event;
            //I'm just adding 1 to it as sample

            int outputResource = inputResource.Resource + 1;

            Console.WriteLine("Unit {0}, input {1} ", this.Name, inputResource.Resource, outputResource);

            OnResourceGenerated(outputResource);
        }      

        protected virtual void OnResourceGenerated(int outputResource)
        {
            Console.WriteLine("Unit {0}, output {1}", this.Name,  outputResource);

             if (ResourceGenerated != null)
                ResourceGenerated(this, new ResourceGeneratedEventArgs(outputResource));
        }
    }


    public class ResourceGeneratedEventArgs : EventArgs
    {
        public ResourceGeneratedEventArgs(int resource)
        {
            Resource = resource;
        }

        public int Resource { get; private set; }
    } 



     /// <summary>
     /// This is just to start the process here, Nothing great here 
     /// </summary>
     interface IInitiatorUnit : IUnit
     {
        void  GenerateResource(int initialValue);
     }


    class InitiatorUnit : Unit, IInitiatorUnit
    {
        //prevents the cycle from going on & on
        bool resetFlag;

        public InitiatorUnit(string name):base(name)
        {

        }

        public void GenerateResource(int initialValue)
        {
            resetFlag = false;
            Console.WriteLine("Initiating Unit {0} value {1}", this.Name, initialValue);
            OnResourceGenerated(initialValue);
        }

        protected override void OnResourceGenerated(int outputResource)
        {
            //Dont raise the event. if the cycle has completed
            if (resetFlag == false)
            {
                resetFlag = true;
                base.OnResourceGenerated(outputResource);
            }
            else
            {
                //do nothing, cycle has completed
                Console.WriteLine("Unit {0}, Cycle complete", this.Name);
            }
        }
    }

编辑 1:处理大量单位的方法

在我的第一种方法中,每个单元调用后续单元创建一个链,就像这样 -在此处输入图像描述

随着节点的增加,调用堆栈的深度也会增加,因此当数量达到数千时,我们可能会超出堆栈限制,从而导致堆栈溢出。

因此,新方法只是对单元进行迭代,给每个单元一个请求,获取响应并将响应作为请求反馈给后续单元。像这样的东西-

在此处输入图像描述

这是一个工作示例,它会生成以下输出 -

单元 A,输入 0 单元 A,输出 1 单元 B,输入 1 单元 B,输出 2 单元 C,输入 2 单元 C,输出 3 循环完成结果 3

客户代码

private void ClientCode()
    {
        // Create an array of units 
        IUnit[] units = new IUnit[] {
            new Unit("A"), // A will be called 1st . It needs to be given an initial value to start processing
            new Unit("B"), // B will get A's Output to process. 
            new Unit("C"), // C will get B's Output to process. 
        };

        // pass the array to workflow to process 
        cycle = new WorkFlow(units);

        Console.ReadLine();
    }

心跳计时器

  void heartBeatTimer_Tick(object sender, EventArgs e)
    {
        var result = cycle.Execute(new Resource(0)); // starting the cycle with initial value of 0

        Console.WriteLine("Cycle completed result {0}", result.Value); 
    }

现在基础设施简单多了,

    interface IUnit
    {
        Resource ProcessResource(Resource inputResource);
        string Name { get; }
    }

    class Unit : IUnit
    {
        public string Name { get; private set; }

        public Unit(string name)
        {
            this.Name = name;
        }

        public Resource ProcessResource(Resource inputResource)
        {
            //take the input resorce. pocess it & fire the event;
            //I'm just adding 1 to it as sample

            int outputResource = inputResource.Value + 1;

            Console.WriteLine("Unit {0}, input {1} ", this.Name, inputResource.Value);
            Console.WriteLine("Unit {0}, output {1} ", this.Name, outputResource);


            return new Resource(outputResource);
        }
    }


    class WorkFlow
    {
        IUnit[] mUnits;

        public WorkFlow(IUnit[] units)
        {
            this.mUnits = units;
        }

        public Resource Execute(Resource initiatingResource)
        {
            Resource result = initiatingResource; // initialise result with the input of the cycle.
            for (int i = 0; i < mUnits.Length; i++)
            {
                // the result is passed as input. 
                //IUnit.ProcessResource function gives back a new result which is encached as input for subsequent resource
                result = mUnits[i].ProcessResource(result);
            }
            return result; // after all are processed, 
        }
    }

    public class Resource
    {
        public Resource(int resourceValue)
        {
            Value = resourceValue;
        }

        public int Value { get; private set; }
    }  

希望现在一切都会好起来。如果有任何不清楚的地方,请给我写评论。

于 2015-10-24T08:33:14.817 回答