我为每个循环运行数据库以检查已标记为要进行转换的文件。目前我有以下代码:
/* All files flagged for invidual conversion will be stored in here. */
ArrayList files = vc.getFilesForInvidualConversion();
foreach (FileInfoExtended file in files)
{
// As long as the status flag hasn't been changed it can continue.
if (abort == false)
{
if (vc.isFileInUse(file) == false)
{
// Converting the video file.
vc.convertVideoToFLV(file);
}
}
vc.getFilesForInvidualConversion();
}
在第一行中,您可以看到我用一个对象填充一个ArrayList,它将为每个对象填充。但是,在列表中的每个文件之后,我想检查可能需要转换的新文件。当我再次填充ArrayList时,似乎没有注意到它们,它继续使用从第一行代码接收的原始文件。我宁愿让它更新“文件”-ArrayList,以便它也可以转换新文件。
这可能吗?
编辑:您为这个场景提供了所有工作的答案,但我想添加一些内容。是否可以在循环期间从列表中删除文件?为了做到这一点它不会转换那个?
编辑2:这就是我现在所拥有的:
List<FileInfoExtended> files = vc.getFilesForInvidualConversion();
while (files.Count > 0)
{
if (abort == false)
{
if (vc.isFileInUse(files[0]))
{
vc.convertVideoToFLV(files[0]);
}
}
files = vc.getFilesForInvidualConversion();
}
它适用于两种情况(将文件添加到列表中以及从列表中删除文件时)。我不知道它是否是性能明智的好解决方案,但现在它适合我的需求。除非有一些我忽视的问题?
任何评论将不胜感激! 亲切的问候, 弗洛
答案 0 :(得分:3)
我建议使用其他一些集合代替ArrayList
。例如Stack<T>
。写这样的smth:
while (stack.Any())
{
var item = stack.Pop();
// convert item
}
// All items were converted
您可以随时stack.Push()
新项目。
P.S。:使用非通用ArrayList
是否有任何意义?
答案 1 :(得分:2)
您可以使用标准的“for”循环。 foreach循环要求集合在遍历期间是不可变的。 'for'循环没有这个约束。但是,在这种情况下,在'for'循环上获取结束条件约束可能很困难。
我会考虑保留已经处理过的文件列表,这样当你第二次通过时,你可以检查一下你是否已经处理过特定文件。
答案 2 :(得分:1)
您可以使用递归将索引传递给递归函数,以便您可以评估数组中的位置。
void ConvertRecursively(int index, typeForVC vc)
{
if(abort)
return;
ArrayList files = vc.getFilesForInvidualConversion();
if(index !< files.Count)
return;
else
{
if (vc.isFileInUse(files[index]) == false)
{
// Converting the video file.
vc.convertVideoToFLV(files[index]);
}
return ConvertRecursive(++index, vc);
}
}
要打电话:
ConvertRecursively(0, typeForVC vc);
更新:如果你需要处理数组大小减小的情况,那么最后一个流控制语句也是不必要的,所以我把它拿出来了:
void ConvertRecursively(int index, int prevSize, typeForVC vc)
{
if(abort)
return;
ArrayList files = vc.getFilesForInvidualConversion();
int sizeDifferential = files.Count <= prevSize ? prevSize - files.Count : 0;
int adjustedIndex = index - sizeDifferential;
if(adjustedIndex !< files.Count)
return;
if (vc.isFileInUse(files[adjustedIndex]) == false)
{
// Converting the video file.
vc.convertVideoToFLV(files[adjustedIndex]);
}
return ConvertRecursive(++adjustedIndex, files.Count, vc);
}
要打电话:
ConvertRecursively(0, 0, typeForVC vc);
好的,现在我只是玩得开心。希望它对你有用。我没有测试过这个b.t.w。
答案 3 :(得分:1)
这样做的理智方法是处理批次:当每个批次完成后,获得另一批,直到您遇到空批次(这与@ j0rd4n建议的方法相同)。以下是如何将这个逻辑包装在一个漂亮的foreach
循环中:首先,创建用于管理迭代的类:
namespace StackOverflow6128549
{
class FileInfoExtended
{
public int PropertyX { get; set; }
}
class IncrediblySmartIteration : IEnumerable<FileInfoExtended>
{
private List<FileInfoExtended> GetFilesToProcess()
{
throw new NotImplementedException();
}
#region IEnumerable<FileInfoExtended> Members
private IEnumerator<FileInfoExtended> InternalGetEnumerator()
{
List<FileInfoExtended> filesToProcess = null;
do
{
filesToProcess = GetFilesToProcess();
foreach (var fi in filesToProcess)
{
yield return fi;
}
}
while (filesToProcess.Count > 0);
}
public IEnumerator<FileInfoExtended> GetEnumerator()
{
return InternalGetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return InternalGetEnumerator();
}
#endregion
}
}
然后,您将能够使用简单的foreach
:
var container = new IncrediblySmartIteration();
foreach (var fi in container)
{
Console.WriteLine(fi.PropertyX);
}
请注意,在设计GetFilesToProcess()方法时,应该关注保证终止。请务必考虑在查找新文件时出现错误。