无限递归 导致堆栈溢出....

bustersword 2011-07-12 01:56:24
我本来发了帖子http://topic.csdn.net/u/20110711/09/9f5bb296-2b43-4ed9-9170-15458e9a7a83.html
用C#写的服务,不知道为什么运行一段时间后自动停止了,我就写成winform,开着测试,结果报了
System.StackOverflowException

在events = new AutoResetEvent(false);
我想知道是什么原因导致的呢?

如果换成 线程里无限循环呢?


用timer 又是怎样的呢?
...全文
462 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
bustersword 2011-07-12
  • 打赏
  • 举报
回复

private System.Threading.Thread timerlisten;
private static Hashtable fileInfos;
private static Hashtable traverse;
private Hashtable tempFiles;
protected void start()
{
fileInfos = new Hashtable();
traverse = new Hashtable();
tempFiles = new Hashtable();
timerlisten = new System.Threading.Thread(
new System.Threading.ThreadStart(monitor));
timerlisten.Start();

FileSystemWatcher curWatcher = new FileSystemWatcher();

curWatcher.BeginInit();
curWatcher.IncludeSubdirectories = true;

curWatcher.Path = System.Configuration.ConfigurationSettings.AppSettings["FileMonitorDirectory"];
//curWatcher.Changed += new FileSystemEventHandler(OnFileChanged);
curWatcher.Created += new FileSystemEventHandler(OnFileCreated);
//curWatcher.Deleted += new FileSystemEventHandler(OnFileDeleted);
//curWatcher.Renamed += new RenamedEventHandler(OnFileRenamed);
curWatcher.EnableRaisingEvents = true;
curWatcher.EndInit();
}

private void OnFileCreated(Object source, FileSystemEventArgs e)
{
if (servicePaused == false)
{
if (!timerlisten.IsAlive)
{
//当有文件创建时,如果检测线程没有运行,那么开启
timerlisten.Start();
}
lock (fileInfos)
{
FileInfo myfile;
try
{
myfile = new FileInfo(e.FullPath);
}
catch
{
//遇到所有异常此次获取文件信息操作均停止
return;
}
string filter = System.Configuration.ConfigurationSettings.AppSettings["filter"];
if (myfile.FullName.IndexOf(filter) == -1)
{
//如果上传的文件不是有upload标识的,不加入hashtable中
return;
}
string fileLength;
try
{
fileLength = myfile.Length.ToString();
}
catch (IOException)
{
return;
}

middleHandle(true, myfile.FullName, fileLength);

}
}
}


AutoResetEvent events;
protected void monitor()
{

events = new AutoResetEvent(false);
WaitCallback wait = new WaitCallback(startagain);
try
{
ThreadPool.QueueUserWorkItem(wait, events);
}
catch
{
return;
}
if (events.WaitOne(-1, true))
{

//Thread.Sleep(1000);
//events.Close();
//monitor();
}


}

//中间处理,hashtable新添加值与监控线程处理hashtable必须互斥
private void middleHandle(bool flag, string name, string length)
{
lock (this)
{
if (true == flag)
{
tempFiles[name] = length;

}
else
{
IDictionaryEnumerator idE = tempFiles.GetEnumerator();

while (idE.MoveNext())
{
fileInfos[idE.Key] = idE.Value;
traverse[idE.Key] = idE.Value;
}
tempFiles.Clear();
}
}
}

void startagain(object obj)
{
if (servicePaused == false)
{


while (true)
{
if (traverse.Count == 0)
{
System.Threading.Thread.Sleep(1000);
middleHandle(false, "", "");
}

IDictionaryEnumerator idE = fileInfos.GetEnumerator();
try
{
while (idE.MoveNext())
{
string oldFile;
string currentFileLength;
FileInfo currentFile;

try
{
if (!traverse.ContainsKey(idE.Key))
{
//如果此键已被处理,则跳出此次操作
continue;
}
else
{
oldFile = traverse[idE.Key].ToString();
}
}
catch (ArgumentNullException)
{
continue;
}
System.Threading.Thread.Sleep(2500);
try
{
currentFile = new FileInfo(idE.Key.ToString());
currentFileLength = currentFile.Length.ToString();
}
catch (FileNotFoundException)
{
traverse.Remove(idE.Key);
continue;
}

if (oldFile == currentFileLength)
{
try
{
currentFile.MoveTo(currentFile.FullName.Replace("upload", ""));
}
catch
{
//意外获取到2次的大小都一样,但是文件还是没传输完,捕获此异常,跳出循环体
continue;
}
traverse.Remove(idE.Key);

}
else
{
traverse[idE.Key] = currentFile.Length.ToString();

}


if (traverse.Count == 0)
{
try
{
fileInfos.Clear();
}
catch
{
break;
}
break;
}
}
}
catch (InvalidOperationException)
{
//枚举操作无效时,直接进入下次循环
continue;
}

}//end while


}

}



这是我现在在运行的...用了个while(true)
不用循环的话。。。用timer?
还是靠什么来触发
  • 打赏
  • 举报
回复
注意,跟“循环”没有关系。不需要循环语句。
  • 打赏
  • 举报
回复
new ThreadStart(....)

这类代码也是一样。如果你在线程中去注册另外一个线程,虽然循环调用test(),但是并不会递归。除非,你将前一个test()方法运行时内部变量作为参数传递给注册的线程,这虽然会使用一些堆栈,但是也跟简单地递归调用test()方法所占用的堆栈大小是完全不同的。

所以,你可以考虑你自己所说的方法,将你原来的简单递归稍微改上一两行代码,加上线程机制。
  • 打赏
  • 举报
回复
[Quote=引用楼主 bustersword 的回复:]
如果换成 线程里无限循环呢?
[/Quote]

假设你在一个方法里,使用类似
public void test()
{
.....
ThreadPool.QueueUserWorkItem(h=> { test(); }
};
这种代码,这并不会造成递归。只有直接调用test()才会递归。
flyerwing 2011-07-12
  • 打赏
  • 举报
回复
死循环??
递归应该都是有限的吧.
bustersword 2011-07-12
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 xuexiaodong2009 的回复:]

代码有问题,
events = new AutoResetEvent(false);
每次都new ,不释放吗?
[/Quote]
我调用close方法的啊
xuexiaodong2009 2011-07-12
  • 打赏
  • 举报
回复
代码有问题,
events = new AutoResetEvent(false);
每次都new ,不释放吗?

110,545

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧