递归调用方法(用于对象重用目的)
我有一个相当大的类,其中包含大量字段(10 +),一个巨大的数组(100kb)和一些非托管资源。 让我举例说明
class ResourceIntensiveClass { private object unmaganedResource; //let it be the expensive resource private byte[] buffer = new byte[1024 * 100]; //let it be the huge managed memory private Action OnComplete; private void DoWork(object state) { //do long running task OnComplete(this); //notify callee that task completed so it can reuse same object for another task } public void Start(object dataRequiredForCurrentTask) { ThreadPool.QueueUserWorkItem(DoWork); //initiate long running work } }
问题是start方法在第10000次迭代后永远不会返回,导致堆栈溢出。 我可以在另一个线程中执行OnComplete委托,让Start方法返回,但是如果你知道的话,它需要使用额外的cpu时间和资源。 那对我来说最好的选择是什么?
是否有理由以递归方式进行计算? 这似乎是一个简单的循环可以解决这个问题,从而避免了对非常深的堆栈的需求。 这种设计似乎特别成问题,因为您依靠main()来设置递归。
递归方法可能会非常快速地失控。 您是否考虑过使用Parallel Linq? 你可以做点什么
(你的数组).AsParallel()。ForAll(item => item.CallMethod());
您还可以查看任务并行库(TPL)
通过任务,您可以定义操作并继续执行任务。
另一方面,Reactive Framework(RX)可以以异步方式处理完整事件。
你在哪里更改taskData
的值,以便它的长度可以等于currentTaskIndex
? 由于您分配给数据的任务永远不会改变,因此它们将永远执行…
我猜这个问题来自于使用预增量运算符:
if(c.CurrentCount < 10000) c.Start(++c.CurrentCount);
我不确定C#中预增量的语义,也许传递给方法调用的值不是你所期望的。
但是,由于你的Start(int)
方法将输入的值分配给this.CurrentCount
因为它是第一步,你应该安全地将其替换为:
if(c.CurrentCount < 10000) c.Start(c.CurrentCount + 1);
分配给c.CurrentCount
两次是没有意义的。
如果使用线程池,我假设您正在保护计数器(c.CurrentCount),否则并发增量将导致更多活动,而不仅仅是10000次执行。
有一个称为ManualResetEvent的简洁工具可以简化您的生活。
在您的类中放置一个ManualResetEvent
并添加一个公共OnComplete
事件。
声明类时,可以将OnComplete
事件连接到代码中的某个位置,或者不将其连接并忽略它。
这将有助于您的自定义类具有更正确的表单。
当你的漫长过程完成时(我猜这是在一个线程中),只需调用ManualResetEvent
的Set方法即可。
至于运行long方法,它应该在一个以类似于下面的方式使用ManualResetEvent
的线程中:
private void DoWork(object state) { ManualResetEvent mre = new ManualResetEvent(false); Thread thread1 = new Thread( () => { //do long running task mre.Set(); ); thread1.IsBackground = true; thread1.Name = "Screen Capture"; thread1.Start(); mre.WaitOne(); OnComplete(this); //notify callee that task completed so it can reuse same object for another task }