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