Начать For l oop частично через словарь - PullRequest
0 голосов
/ 02 августа 2020

Приведенный ниже код пытается работать через словарь, переданный в эту подпрограмму (это не вся подпрограмма - как раз то, что, как я думал, было необходимо для этого вопроса), используя ключ словаря и значение для копирования файлов. Работает нормально. Я пытаюсь разрешить пользователю нажать кнопку «Пауза», а затем нажать кнопку «Возобновить». Как видно из этого кода, я сохраняю значение счетчика, когда нажимается пауза в переменной holdctr1. Что мне нужно сделать, так это снова запустить процесс с переменной holdctr1, когда пользователь нажимает «Возобновить». С обычным оператором For, который включает предложение From, это легко, но я не вижу, как это сделать здесь. Я думаю, что вместо использования целочисленного счетчика я должен использовать значение ключа словаря, но всякий раз, когда я пытаюсь поместить предложение From в оператор For, я получаю сообщение об ошибке. Буду признателен за любую помощь, но, пожалуйста, будьте проще, так как я только изучаю VB.

    For Each kvp In DirectCast(e.Argument, Dictionary(Of String, String))
        counter1 += 1

        ' Has the background worker been told to stop?
        If Me.BackgroundWorker1.CancellationPending Then
            ' Set cancel to True
            e.Cancel = True
            ' ***********************************
            ' hold the counter value when  ******
            ' pause was pressed            ******
            holdctr1 = counter1 - 1       '******
            ' ***********************************
            Exit For
        End If

        strSourceFilePath = kvp.Key
        strDestFilePath = kvp.Value

        ' Do the file copy here
        My.Computer.FileSystem.CopyFile(strSourceFilePath, strDestFilePath, overwrite:=False)

    Next

Ответы [ 2 ]

1 голос
/ 02 августа 2020

A For Each l oop перечисляет список, и вы можете вызвать Skip в этом списке, чтобы игнорировать заданное c количество ведущих элементов. В вашем случае это будет означать использование этого:

For Each kvp In DirectCast(e.Argument, Dictionary(Of String, String)).Skip(counter1)

Конечно, вы должны использовать для этой переменной имя лучше, чем counter1.

0 голосов
/ 03 августа 2020

В качестве альтернативы перезапуску перечисления и пропуску вперед вы можете написать перечисление явно, выписав шаги, которые For Each выполняет за вас за кулисами. Затем вы можете оставить перечислитель на уровне класса, что сделает его тривиальным для возобновления.

например, переменная класса

Private _pathsEnumerator As Dictionary(Of String, String).Enumerator

(К сожалению, поскольку это уровень класса, тип может ' t может быть выведено.)

И тогда ваша итерация будет примерно такой:

_pathsEnumerator = DirectCast(e.Argument, Dictionary(Of String, String).GetEnumerator()

Do While _pathsEnumerator.MoveNext()
    Dim kvp = _pathsEnumerator.Current

    'Remainder would be the same 
Loop

'Reset the enumerator if canceled.
If e.Cancel Then _pathsEnumerator = Nothing

Написанная таким образом, вы можете продолжить, проверив, является ли перечислитель нулевым, и продолжить, если нет . Помните, что если есть шанс изменения словаря, это вызовет исключение, но вы, вероятно, все равно этого захотите; Я бы побеспокоился о logi c в другом ответе, если бы это произошло, вы могли бы обнаружить, что, возобновив работу, вы случайно что-то пропустили.

Возможно, вы захотите отложить проверку отмены до тех пор, пока не выполните операцию текущий элемент; в противном случае вам понадобится лог c для управления повторением этого элемента при возобновлении. Это, вероятно, потребует отслеживания «текущего элемента» в дополнение к перечислителю. Реализация оставлена ​​читателю в качестве упражнения.

...