2011-05-25 98 views
2

我有一个运行数据库的每个循环来检查已标记转换的文件。目前,我有以下代码:对于每个具有动态列表?

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

而且它在这两种情况下(当文件被添加到列表中,当一个文件被从列表中删除)的作品。我不知道性能是否是一个好的解决方案,但现在它适合我的需求。除非我忽略了一些问题?

如有任何意见,将不胜感激! 亲切的问候, Floris

+2

尝试使用而不是foreach。 foreach依靠收藏在其生活中不会改变。 – 2011-05-25 17:43:41

+0

我不知道,这清除了很多东西!感谢您的信息。 – 2011-05-25 18:15:19

+0

这应该工作得很好。 – 2011-05-26 17:17:03

回答

2

您可以使用标准的'for'循环。 foreach循环要求集合在遍历期间是不可变的。 'for'循环没有这个约束。然而,在这种情况下,获得'for'循环的结束条件约束可能会很困难。

我会考虑保留已处理文件的列表,以便在第二次通过时,您可以检查是否已处理特定文件。

+0

我不知道'每个'循环与不可变集合一起工作,这清除了很多东西!感谢您的信息。我认为你的回答和保罗凯瑟斯会帮助我。 – 2011-05-25 18:17:32

3

我会推荐使用其他集合而不是ArrayList。例如Stack<T>。并写下如下:

while (stack.Any()) 
{ 
    var item = stack.Pop(); 
    // convert item 
} 

// All items were converted 

在任何时候你可以stack.Push()新项目。

P.S .:是否有使用非通用的ArrayList

+0

在编写ArrayList的时候,我曾经使用过另一种存储在ArrayList中的对象,实际上我忘了纠正这个问题,谢谢你的提醒。至于你的答案,我会研究所有这些,并使用最适合我的那个。 – 2011-05-25 18:19:52

+0

它会适合我的需要,如果它会采用其他方式,但它不会。检查我原来的帖子编辑,看看我的意思。 – 2011-05-26 14:25:45

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.

+0

它只适用于将文件添加到列表中,而不是在删除文件时使用。 – 2011-05-26 14:24:51

+0

可以调整,这只是一个起点。该项目在哪里被从名单中删除?它应该工作,除非它从索引<=我们的索引变量从列表中移除。 – 2011-05-26 14:40:24

+1

@弗洛里斯,在这个(我更新的)场景中,只要文件还没有被转换,并且从列表中删除,你应该没问题。 – 2011-05-26 14:52:25

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()方法时,应该关心保证终止。一定要考虑在寻找新文件时出现错误会发生什么。

+0

您的方法适用于我所问的问题,谢谢。但我注意到它不能以其他方式工作。例如,当一个文件已被另一个服务转换时。然后,我需要从列表中删除该文件。但是如果我用这种方法测试它仍然会被转换。 – 2011-05-26 10:16:19

相关问题