Что нового

Подобие многопоточности?

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 320
Как известно, AutoIt не поддерживает многопоточность, но одновременно можно запустить несколько скриптов. Я не знаю, насколько это правильно, но так у меня получилось найти все файлы на всех дисках и записать их пути в файл значительно быстрее, чем, если это делает один скрипт.
1. Файл FileSearch.au3 (должен лежать в одной папке со следующем скриптом).
Код:
#NoTrayIcon
If $CmdLine[0] <> 2 Then
	ConsoleWrite('Error CmdLine')
	Exit
EndIf
$sText = ''
$aReturn = _FileSearch($CmdLine[1])
If @error Then
	ConsoleWrite('Error _FileSearch')
	Exit
EndIf
For $i = 1 To $aReturn[0]
	$sText &= $aReturn[$i] & @CRLF
Next
$hFile = FileOpen($CmdLine[2], 2)
If $hFile = -1 Then
	ConsoleWrite('Error FileOpen')
	Exit
EndIf
FileWrite($hFile, $sText)
FileClose($hFile)
ConsoleWrite('OK')

Func _FileSearch($s_Path_Search, $s_File_Mask = '*', $i_Flag = 1, $i_SubDir = 1)
	Local $s_Out, $a_Out, $s_Read, $h_Dir, $s_Attrib, $s_Subdir, $a_Masks

	If StringRight($s_Path_Search, 1) == '\' Then
		$s_Path_Search = StringTrimRight($s_Path_Search, 1)
	EndIf
	If $i_SubDir Then
		$s_Subdir = ' /S /B'
	Else
		$s_Subdir = ' /B'
	EndIf
	Switch $i_Flag
		Case 1
			$s_Attrib = ' /A-D'
		Case 2
			$s_Attrib = ' /AD'
		Case Else
			$s_Attrib = ' /A'
	EndSwitch
	$s_Out = StringToBinary('0' & @CRLF, 2)
	$a_Masks = StringSplit($s_File_Mask, ';')
	For $i = 1 To $a_Masks[0]
		$h_Dir = Run(@ComSpec & ' /U /C DIR "' & $s_Path_Search & '\' & $a_Masks[$i] & '"' & $s_Subdir & $s_Attrib, @SystemDir, @SW_HIDE, 6)
		If Not $h_Dir Then Return SetError(1)
		While 1
			$s_Read = StdoutRead($h_Dir, False, True)
			If @error Then
				ExitLoop
			EndIf
			If $s_Read Then
				$s_Out &= $s_Read
			EndIf
			Sleep(10)
		WEnd
	Next
	$a_Out = StringRegExp(BinaryToString($s_Out, 2), '[^\r\n]+', 3)
	If @error Then Return SetError(1)
	$a_Out[0] = UBound($a_Out) - 1
	Return $a_Out
EndFunc   ;==>_FileSearch
2. Скрипт.
Код:
#include <Constants.au3>
#include <File.au3>
#include <Array.au3>

$sFile = @ScriptDir & '\All_Files_Drive_'

$i_Start = TimerInit()
$aDrive = DriveGetDrive('FIXED')
If @error Then
	MsgBox(16, 'Error', 'DriveGetDrive')
	Exit
EndIf

Dim $aResult[$aDrive[0] + 1][6] = [[$aDrive[0], $aDrive[0]]]
#cs
	0 - parameter
	1 - TempFile
	2 - PID
	3 - Read
	4 - error
	5 - Time
#ce
For $i = 1 To $aResult[0][0]
	$aResult[$i][0] = StringUpper($aDrive[$i])
	$aResult[$i][1] = _TempFile()
	$aResult[$i][4] = FileInstall('FileSearch.au3', $aResult[$i][1], 1)
	If $aResult[$i][4] Then
		$sFileRes = '"' & $sFile & StringRegExpReplace($aResult[$i][0], '[^A-Z]', '') & '.txt"'
		$sParameter = '"' & $aResult[$i][1] & '" "' & $aResult[$i][0] & '" ' & $sFileRes
		If @Compiled Then
			$aResult[$i][2] = Run('"' & @ScriptFullPath & '" /AutoIt3ExecuteScript ' & $sParameter, _
					'', @SW_HIDE, $STDOUT_CHILD)
		Else
			$aResult[$i][2] = Run('"' & @AutoItExe & '" /AutoIt3ExecuteScript ' & $sParameter, _
					'', @SW_HIDE, $STDOUT_CHILD)
		EndIf
		If Not $aResult[$i][2] Then $aResult[$i][4] = 0
		If $aResult[$i][2] Then $aResult[$i][5] = TimerInit()
	EndIf
Next
While TimerDiff($i_Start) < 600000
	For $i = 1 To $aResult[0][0]
		If $aResult[$i][4] Then
			$aResult[$i][3] &= StdoutRead($aResult[$i][2])
			If @error Then
				$aResult[$i][4] = 0
				$aResult[0][1] -= 1
				$aResult[$i][5] = StringFormat('%.2f sec', TimerDiff($aResult[$i][5]) / 1000)
			EndIf
		EndIf
	Next
	If Not $aResult[0][1] Then ExitLoop
	Sleep(50)
WEnd
For $i = 1 To $aResult[0][0]
	FileDelete($aResult[$i][1])
Next
_ArrayDisplay($aResult, StringFormat('%.2f sec', TimerDiff($i_Start) / 1000))
Запускаем скрипт и ждем результат. У меня 6 дисков обработаны менее, чем за 1 минуту.
 
Верх