3

Я создал сценарий PowerShell, который копирует все загружаемые мною электронные книги в заранее определенный каталог, который периодически сканируется моим менеджером электронных книг и добавляется в мою библиотеку. Скрипт запускается сразу после каждой загрузки.

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

Поэтому я хотел бы поставить в очередь копирование с помощью заданий PowerShell, но я не знаю, как создать одну очередь (единый параллелизм), чтобы каждое последующее задание ожидало завершения каждого более старого задания.

То есть я хотел бы, чтобы скрипт создавал задание (назовем его "Книжное задание"), которое периодически проверяет очередь запуска Книжных заданий, чтобы увидеть, все ли старые работы с книгами завершились до того, как он запустится. Когда оно завершается, Книжное задание должно объявить, что оно каким-то образом завершено, что может быть обнаружено более молодыми Книжными заданиями.

Кто-нибудь знает, как я могу это сделать? Я увидел похожий вопрос, на который я смотрю: фоновые задачи Powershell, однако, в моем случае я запускаю скрипт несколько раз (после каждой новой загрузки).

1 ответ1

3

Моя мысль состоит в том, чтобы создать очередь, создавая один файл блокировки для каждого нового экземпляра вашего скрипта. При запуске сценария он проверяет каталог, предназначенный для отслеживания очереди на наличие существующих экземпляров сценария. Если их нет, скрипт добавляет себя в начало очереди, выполняет какое-то действие (запускает ваш код), а затем очищает свою блокировку. Если существуют блокировки, новая будет добавлена в конец очереди, и экземпляр будет бесконечно проверяться, пока не окажется в начале очереди.

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

Файлы блокировки структурированы как Индекс, разделитель ("_"), идентификатор процесса.

Clear-Host

function New-Lock ([int] $index) {
    $newLock = "$index" + "_" + $pid + ".lck"
    New-Item $queue$newLock | Out-Null
}

$queue = "C:\locks\"

# find the end of the stack
$locks = gci $queue *.lck | sort | select -expandproperty name

# if locks exist, find the end of the stack by selecting the index of the last lock
if($locks) {
    # gets the last lock file, selects the index by splitting on the delimiter
    [int]$last = [convert]::ToInt32(($locks | select -last 1).Split("_")[0],10)

    # add the lock to the end of the stack
    New-Lock ($last + 1)
}
# if no locks exist, create one at the top of the stack
else {
    New-Lock 0
}

# check if we're at the top of the stack
do {
    $locks = gci $queue *.lck | sort | select -expandproperty name

    # this is the PID on the top of the stack
    [int]$top = [convert]::ToInt32(($locks | select -first 1).Split("_")[1].Split(".")[0],10)
    write-verbose "not at the top..."
    sleep 1
} until ($pid -eq $top)

# if we're here, we've been to the top. it's our turn to do something
Write-Verbose "we've reached the top!"
# <do something. put your code here>
# might be good to add some Start-Sleep here
# </do something put your code here>

# now that we're done, let's delete our lock
gci $queue | select -first 1 | Remove-Item

Ниже приведен пример вымышленной временной шкалы, в котором вы загрузили три файла (я выбрал случайные PID).

  • Файл 1 загружается и запускает скрипт. Там нет существующих замков. Создать блокировку "0_19831". Мы находимся на вершине стека, поэтому ваш код выполняется. Это большая электронная книга, поэтому запуск кода передачи файлов займет всего минуту.
  • Файл 2 загружается и запускает скрипт. Блокировка (и) существуют. Создать блокировку "1_332". Мы не на вершине стека, поэтому мы подождем в нашем do/until и продолжим проверять, пока не окажемся первыми в очереди.
  • Файл 1 закончил копирование. Удалить блокировку "0_19831".
  • Файл 3 загружается и запускает скрипт. Блокировка (и) существуют. Создать блокировку "2_7582". Мы не на вершине стека, подождите, пока мы не.
  • Файл 2 закончил копирование. Удалить блокировку "1_332".
  • Файл 3 закончил копирование. Удалить блокировку "2_7582".

Это решение не является пуленепробиваемым, но может работать в зависимости от масштаба.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .