C# 临时存储一个代理以备以后调用

C# 临时存储一个代理以备以后调用,c#,multithreading,.net-4.0,visual-c#-express-2010,C#,Multithreading,.net 4.0,Visual C# Express 2010,在进行异步操作时,我想使用列表将操作存储到框架中。 然后,当框架同步时,我将循环遍历列表并执行操作 有没有办法做到这一点,把重点放在这一点上: -无反射/动态声音。 -不为每个要调用的新方法创建类/结构。 -类型安全。 -将操作存储在列表中。 -存储不同类型的方法和参数。 -稍后执行列表 我不想使用反射的原因是因为它是一个性能问题。它将被频繁使用。 在本例中,它与游戏相关,但该代码可以作为一个全面的代码使用,如果可以避免反射/动态Voke,那么它将非常适合多线程 如果这是不可能的,那么还有其他好

在进行异步操作时,我想使用列表将操作存储到框架中。
然后,当框架同步时,我将循环遍历列表并执行操作

有没有办法做到这一点,把重点放在这一点上:
-无反射/动态声音。
-不为每个要调用的新方法创建类/结构。
-类型安全。
-将操作存储在列表中。
-存储不同类型的方法和参数。
-稍后执行列表

我不想使用反射的原因是因为它是一个性能问题。它将被频繁使用。
在本例中,它与游戏相关,但该代码可以作为一个全面的代码使用,如果可以避免反射/动态Voke,那么它将非常适合多线程

如果这是不可能的,那么还有其他好的选择吗

我在代码中做了一个示例,但它使用反射,并且不是类型安全的。
基本步骤是:
1.用具有多个不同参数的方法填充列表。
2.循环浏览列表并使用这些参数执行所有方法。
3.清除下一个周期的列表

{
    struct MyDelayedCaller
    {
        public Delegate TheTarget;
        public object[] MyParameters;

        public MyDelayedCaller(Delegate target, object[] parameters)
        {
            TheTarget = target;
            MyParameters = parameters;
        }
    }

    List<MyDelayedCaller> Temporary = new List<MyDelayedCaller>();
    void Update()
    {
        //something happened and another class needs to know
        //but it will have to wait for the sync so as to not cause any treading problems

        Temporary.Add(new MyDelayedCaller(new DelDoSomething1(DoSomething1), new object[] { 10, false }));
        Temporary.Add(new MyDelayedCaller(new DelDoSomething1(DoSomething1), new object[] { 11, true }));

        Temporary.Add(new MyDelayedCaller(new DelDoSomething3(DoSomething3), new object[] { "Some text" }));
        Temporary.Add(new MyDelayedCaller(new DelDoSomething2(DoSomething2), new object[] { 1, 9999, 0.4f }));
    }
    void Sync()
    {
        foreach (var item in Temporary)
        {
            item.TheTarget.DynamicInvoke(item.MyParameters);
        }
        Temporary.Clear();
    }

    delegate void DelDoSomething1(int index, bool alive);
    void DoSomething1(int index, bool alive)
    {

    }
    delegate void DelDoSomething2(int index, int amount, float scale);
    void DoSomething2(int index, int amount, float scale)
    {

    }
    delegate void DelDoSomething3(string text);
    void DoSomething3(string text)
    {

    }
}
{
结构MyDelayedCaller
{
公众代表目标;
公共对象[]MyParameters;
公共MyDelayedCaller(委托目标,对象[]参数)
{
目标=目标;
MyParameters=参数;
}
}
List Temporary=新列表();
无效更新()
{
//发生了一些事情,另一个班级需要知道
//但它必须等待同步,以免造成任何踩踏问题
添加(新的MyDelayedCaller(新的DelDoSomething1(DoSomething1),新的对象[]{10,false});
Add(新的MyDelayedCaller(新的DelDoSomething1(DoSomething1),新的对象[]{11,true});
添加(新的MyDelayedCaller(新的DelDoSomething3(DoSomething3),新对象[]{“一些文本”});
添加(新的MyDelayedCaller(新的DelDoSomething2(DoSomething2),新对象[]{19999,0.4f});
}
void Sync()
{
foreach(临时中的var项目)
{
item.TheTarget.DynamicInvoke(item.MyParameters);
}
临时的。清除();
}
委托void DelDoSomething1(int索引,bool活动);
void DoSomething1(int索引,bool活动)
{
}
委托无效DelDoSomething2(整数索引、整数金额、浮动比例);
void DoSomething2(整数指数、整数金额、浮动比例)
{
}
委托无效DelDoSomething3(字符串文本);
void DoSomething3(字符串文本)
{
}
}

我想说以下几点:

  • imydlayedcaller
    界面:

    interface IMyDelayedCaller
    {
        void Invoke();
    }
    
  • MyDelayedCaller
    泛型类集:

    class MyDelayedCaller<T1> : IMyDelayedCaller
    {
        private Action<T1> _target;
        public T1 _param;
    
        public MyDelayedCaller(Action<T1> target, T1 parameter)
        {
            _target = target;
            _param = parameter;
        }
    
        public void Invoke()
        {
            _target(_param);
        }
    }
    
    class MyDelayedCaller<T1, T2> : IMyDelayedCaller
    {
        private Action<T1, T2> _target;
        public T1 _param1;
        public T2 _param2;
    
        public MyDelayedCaller(Action<T1, T2> target, T1 param1, T2 param2)
        {
            _target = target;
            _param1 = param1;
            _param2 = param2;
        }
    
        public void Invoke()
        {
            _target(_param1, _param2);
        }
    }
    
  • 你可以在第四站停车。通过提供允许编译器推断您的类型参数的静态类更容易:

    static class MyDelayedCaller
    {
        public static MyDelayedCaller<T1> Create<T1>(Action<T1> target, T1 param)
        {
            return new MyDelayedCaller<T1>(target, param1);
        }
    
        public static MyDelayedCaller<T1, T2> Create<T1, T2>(Action<T1, T2> target, T1 param1, T2 param2)
        {
            return new MyDelayedCaller<T1, T2>(target, param1, param2);
        }
    }
    
    您可以在并行集合中对输入和操作进行排队:
    var actions=newdictionary();
    var输入=新字典();
    //当您要存储操作及其输入时
    int计数器=0;
    object[]someObjects=新对象[]{};
    Add(计数器,x=>{return x[0];});
    输入。添加(计数器、某些对象);
    计数器++;
    //然后等到执行的时候
    foreach(输入中的var输入)
    {
    操作[input.Key].Invoke(input.Value);
    }
    

    或者,您可以滚动一个同时存储输入和操作的类,以便在执行时输入通过匹配的字典键以外的其他方式耦合到操作。

    我的另一个答案显示了非常复杂的方法。然而,有一个更容易。你为什么不把清单列出来呢

    List Temporary=新列表();
    无效更新()
    {
    //发生了一些事情,另一个班级需要知道
    //但它必须等待同步,以免造成任何踩踏问题
    临时添加(()=>DoSomething1(1,true));
    临时添加(()=>DoSomething3(“一些文本”);
    }
    void Sync()
    {
    foreach(临时中的var项目)
    {
    item.Invoke();
    }
    临时的。清除();
    }
    

    应该没问题。

    我希望我能理解这个问题,因为答案似乎很简单:只需存储一个
    列表即可。你想放什么就放什么。您可以枚举列表并调用所有内容

    您完全可以将参数化调用添加到这样的列表中:
    ()=>DoSomething1(10,false)
    。参数封装在
    操作
    中。C#编译器生成一个(强类型)闭包类,并为您完成所有这些工作


    这不符合您的要求吗?

    @Eli,您在for循环中得到4作为输入值,因为操作的执行被延迟。当它们实际执行时,i=4

    要避免这种情况,请将输入排队


    我会对你的评论发表评论,但还没有代表。

    这太棒了,正是我需要的。然而,当我为(inti=0;I<4;I++){Temporary.Add(()=>DoSomething(I,true));}编写for循环时,我遇到了一个奇怪的,可能是一个优化错误。如果我做一个int a=I;&将a而不是i传递给DoSomething,则它是正确的值。在我看来,我可以在不知不觉中犯下严重的错误。。。有什么想法吗?用我的另一个答案来排除这种可能性。你不能用
    动作
    替换这个界面吗?@usr你不能从
    动作
    派生出来。但是您可以创建列表
    list
    。我意识到在发布这个答案后,这就是为什么我添加了另一个答案,这个解决方案。这很好,+能够向MyDelayCaller添加额外的信息,以查看何时和谁调用它进行调试等。只绘制
    Temporary.Add(new MyDelayedCaller<int, bool>(DoSomething1, 10, true));
    Temporary.Add(new MyDelayedCaller<string>(DoSomething3, "Some text"));
    
    foreach (var item in Temporary)
    {
        item.Invoke();
    }
    Temporary.Clear();
    
    static class MyDelayedCaller
    {
        public static MyDelayedCaller<T1> Create<T1>(Action<T1> target, T1 param)
        {
            return new MyDelayedCaller<T1>(target, param1);
        }
    
        public static MyDelayedCaller<T1, T2> Create<T1, T2>(Action<T1, T2> target, T1 param1, T2 param2)
        {
            return new MyDelayedCaller<T1, T2>(target, param1, param2);
        }
    }
    
    Temporary.Add(MyDelayedCaller.Create(DoSomething1, 10, true));
    Temporary.Add(MyDelayedCaller.Create(DoSomething3, "Some text"));
    
    You could queue up your inputs and actions in parallel collections:
    
    
    
                var actions = new Dictionary<int, Func<object[], object>>();
                var inputs = new Dictionary<int, object[]>();
    
                //when you want to store the action and it's input
                int counter = 0;
                object[] someObjects = new object[] {};
                actions.Add(counter, x => { return x[0]; });
                inputs.Add(counter, someObjects);
                counter++;
    
    
                //and then later when it's time to execute
                foreach (var input in inputs)
                {
                    actions[input.Key].Invoke(input.Value);
                }
    
    List<Action> Temporary = new List<Action>();
    void Update()
    {
        //something happened and another class needs to know
        //but it will have to wait for the sync so as to not cause any treading problems
    
        Temporary.Add(() => DoSomething1(1, true));
        Temporary.Add(() => DoSomething3("Some text"));
    }
    void Sync()
    {
        foreach (var item in Temporary)
        {
            item.Invoke();
        }
        Temporary.Clear();
    }