Для каждого с динамическим списком? - PullRequest
2 голосов
/ 25 мая 2011

У меня есть для каждого цикла, который проходит через базу данных, чтобы проверить файлы, которые были помечены для преобразования. В настоящее время у меня есть следующий код:

            /* 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, каждый из них, кажется, не замечает, он продолжает работать с исходными файлами, полученными из первой строки кода. Я бы предпочел, чтобы он обновил «files» -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

Ответы [ 4 ]

3 голосов
/ 25 мая 2011

Я бы порекомендовал использовать какую-то другую коллекцию вместо ArrayList.Например Stack<T>.И напишите что-нибудь так:

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

// All items were converted

В любой момент вы можете stack.Push() новые предметы.

PS: есть ли смысл использовать неуниверсальные ArrayList?

2 голосов
/ 25 мая 2011

Вы можете использовать стандартный цикл for. Циклы foreach требуют, чтобы коллекция была неизменной во время обхода. Цикл for не имеет этого ограничения. Однако получение ограничений конечного условия в цикле for в этом случае может быть затруднено.

Я бы хотел сохранить список уже обработанных файлов, чтобы при повторном прохождении вы могли просто проверить, обрабатывали ли вы уже определенный файл.

1 голос
/ 25 мая 2011

Разумный способ сделать это - обработать партии: когда каждая партия сделана, получайте другую, пока не достигнете пустой (это тот же подход, который предложен @ 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 (). Обязательно подумайте, что произойдет, если при поиске новых файлов возникнет ошибка.

1 голос
/ 25 мая 2011

Вы можете использовать рекурсию, передавая индекс в рекурсивную функцию, чтобы вы могли оценить свое местоположение в массиве.

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.

...