Author Topic: Работа одновременно двух программ с курсором  (Read 3719 times)

0 Members and 1 Guest are viewing this topic.

Khodorko

  • Зашел в гости
  • *
  • Posts: 7
    • View Profile
Всем привет. Мне нужно, чтобы на одном рабочем столе работали сразу два запущенных clickermanna, каждый в своём окне(привязка к окну не работает). Оба кликера часто используют курсор мыши, из-за чего возникают конфликты и нормальная работа невозможна. Я попробовал решить проблему так: создал внешний txt файл, в который каждый кликер, каждый раз перед тем, как задействует курсор мыши, пишет в первую строку цифру 1, после того, как мышь становится не нужна - возвращает 0. Соответственно, каждый из кликеров, перед тем, как задействовать курсор, проверяет эту строку, если там 1- ждёт, если 0 - записывает 1 и использует курсор. Получается поочерёдная работа, и друг другу они не мешают. Но возникла проблема: спустя некоторое время после нормальной работы, один из кликеров выбивает окно с ошибкой чтения этой самой строки (TFREAD). Если я правильно понял, это происходит из-за того, что он начинает считывать именно в то мгновение, когда второй кликер перезаписывает эту строку, и она оказывается пустой. Из-за этого приостанавливается работа одной из программ (что категорически не нужно). Пробовал в настройках кликера ставить галочку "Игнорировать ошибки", но это не помогает, ошибка всё равно выскакивает. Вопрос такой, что можно сделать в этой ситуации, как её избежать, или как заставить кликер её игнорировать и продолжать работу? Или, может быть, есть другой способ одновременно организовать работу кликеров с одним курсором?

ya12

  • Активный участник
  • ***
  • Posts: 165
    • View Profile
Понадобилась синхронизация 2х Кликерманов на 2х компах - изменяй название каталога в общей папке.
На 1 компе - синхронизируй через потоки.
« Last Edit: February 08, 2019, 09:18:40 AM by ya12 »

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Чтение INI файла не приводи к ошибке во время перезаписи.
Code: (clickermann) [Select]
INIWRITE("config.ini", "parname", "1")
INIREAD("config.ini", "parname")

4.У.В.@.К

  • Активный участник
  • ***
  • Posts: 117
    • View Profile
АнархияЛогика - мать порядка!
 вместо двух кликеров сделайте два потока.
 вместо записи в текстовый документ, сможете  использовать 0 и 1 в значении переменной.

Понадобилась синхронизация 2х Кликерманов на 2х компах - изменяй название каталога в общей папке.
На 1 компе - синхронизируй через потоки.

Скажите пожалуйста, в чем преимущество двух потоков перед одним, в этой задаче. И есть ли примеры, где многопоточность необходима?
В большинстве случаев многопоточность это лишние извращения. Использовать один курсор потоки все равно будут по очереди, по каким то условиям. Почему-же не использовать этот самый курсор в одном потоке и тоже по условиям?
Спасибо.

ya12

  • Активный участник
  • ***
  • Posts: 165
    • View Profile
В этом не знаю, а у меня один поток - удаленное управление. Другой ждет нажатие клавиш и контролирует уровень жизни. Третий - наведение и общий контроль навигации, четвертый бег, пятый повороты, шестой - режим боя.  У каждого свои задержки, в зависимости от ситуации одни потоки останавливают и запускают другие. К тому же тестировать большую задачу разбитую на отдельные логические элементы проще.



4.У.В.@.К

  • Активный участник
  • ***
  • Posts: 117
    • View Profile
В этом не знаю, а у меня один поток - удаленное управление. Другой ждет нажатие клавиш и контролирует уровень жизни. Третий - наведение и общий контроль навигации, четвертый бег, пятый повороты, шестой - режим боя.  У каждого свои задержки, в зависимости от ситуации одни потоки останавливают и запускают другие. К тому же тестировать большую задачу разбитую на отдельные логические элементы проще.

Наворочено конечно. :) Спасибо за ответ.

Но можно наверно всё это написать и по другому, в одном потоке. Предположительно конечно (задачи я не видел).
Принцип такого сценария в том, что интерпретатор не задерживается во внутренних логических элементах скрипта. Он всегда стремится прочитать скрипт от начала и до конца (полный цикл). Логические элементы расположены в скрипте сверху вниз по приоритету проверяемых в них условий и выполняемых ими действий. Каждый такой элемент, после выполнения его условий может направить интерпретатор по "короткому циклу вычислений". То есть, проверка условий с высшим приоритетом будет происходить чаще. Сами эти логические блоки собственных задержек не имеют, а действия в них могут быть пропущены, по каким-либо условиям, например по таймауту. Так сценарий стремится минимизировать количество условий своего полного цикла (особенно для верхнего уровня вложенности), т.е. "нет команды к действию - идем дальше". Действия выполняются немедленно, непосредственно в этих блоках.
По необходимости блоки можно оформить как подпрограммы. Работать с таким кодом удобно. Применение естественно ситуативное.

В варианте скрипта с несколькими потоками, кажется, что скрипт может быстрее среагировать на команды отдельных потоков. Но не стоит забывать, что каждый такой поток имеет собственную задержку и часть времени тупо простаивает. А если не простаивает, то неоправданно грузит процессор. Так что не факт, что многопоточный скрипт быстрее однопоточного. Пытаясь сэкономить время распараллеливанием вычислений, мы вынуждены вставлять в скрипт паузы. Где логика? Всё естественно зависит от ситуации, но не стоит наверно пихать потоки везде где надо и не надо. Так не стоит оборачивать в THREAD поиск одного пикселя в известных координатах и клик по нему. Потоки оправданы, если в них например крутятся циклы с долгими вычислениями. Это лично мое мнение, и я никому его не навязываю. Вообще потоки штука хорошая.

Вот примерный шаблон сценария из шести условий, заменяющих потоки (про goto я в курсе  :) ).

Code: (clickermann) [Select]
start:

WAITMS(30) // общая задержка полного/короткого цикла

GETSCREEN // общий GETSCREEN

IF(PXL(506,368) ! 16711858) // Если окно игры не распознано
   IF($var = 3)
      GOTO(start) // ожидаем появления окна игры (короткий цикл)
   ELSE
      HALT
   END_IF
END_IF
//------------------------- Удаленное управление (логический элемент)
IF($var = 5)
   // действие и переход на короткий цикл
   GOTO(start)
END_IF
// продолжение длинного цикла
//------------------------- Нажатие клавиш и уровень жизни
IF( (ISKEYDOWN(87) = 0) & (ISKEYDOWN(83) = 0) & (ISKEYDOWN(65) = 0) & (ISKEYDOWN(68) = 0) ) // #W,#S,#A,#D
   // действие и переход на короткий цикл
   GOTO(start)
END_IF
//------------------------- Наведение и общий контроль навигации
IF(PXL(10,10) = 255)
   // действие и переход на короткий цикл
   GOTO(start)
END_IF
//------------------------- Бег
IF(...)
   // действие и продолжение длинного цикла
END_IF
//------------------------- Повороты
IF($lock_spin < $_time_t) // не чаще одного раза в секунду
   IF($var > 45)
      // действие и переход на короткий цикл
      $lock_spin = $_time_t + 1
      GOTO(start)
   END_IF
END_IF
//------------------------- Режим боя
IF(...)
   // действие
   GOTO(start)
END_IF
//-------------------------
// действий небыло
GOTO(start)

Космич

  • Активный участник
  • ***
  • Posts: 265
    • View Profile
То же самое, без циклов. Таким образом можно "распараллеливать" выполнение скрипта без потоков
Code: (clickermann) [Select]
IF($camouflage != 0 & $time_camouflage < $_time_t)
   SWITCH($search_clo4k)
   CASE(0)
      GETSCREEN    ($FlashPlayer_left, $FlashPlayer_top, $FlashPlayer_width, $FlashPlayer_height)
      IF_PICTURE_IN($FlashPlayer_left, $FlashPlayer_top, $FlashPlayer_width, $FlashPlayer_height, STRCONCAT("data\pictures\camouflage_", STRCUT("XL,XS", $clo4k_type, 2), ".bmp"), -1, 100)
         $_xclo4k = $_return1
         $_yclo4k  = $_return2
         $search_clo4k = 2
         $clo4k_type = STRCUT("XL,XS",    $clo4k_type, 2)
         PRINT("Камуфляжный процессор: ", $clo4k_type)
      ELSE
         $clo4k_type = $clo4k_type + 4
      END_IF
      IF($clo4k_type == 8)
         PRINT("Камуфляжный процессор не найден")
         $camouflage = 0
      END_IF
   CASE(1)
      GETSCREEN  ($_xclo4k - 17, $_yclo4k - 13, $_xclo4k + 17, $_yclo4k + 24)
      IF(PXLCOUNT($_xclo4k - 17, $_yclo4k - 13, $_xclo4k + 17, $_yclo4k + 24, 2959912) != 0)
         PRINT("Камуфляжный процессор: ", $clo4k_type, " израсходован")
         $camouflage = 0
      ELSE
         $search_clo4k = 2
      END_IF
   CASE(2)
      GETSCREEN  ($_xclo4k - 17, $_yclo4k - 13, $_xclo4k + 17, $_yclo4k - 9)
      IF(PXLCOUNT($_xclo4k - 17, $_yclo4k - 13, $_xclo4k + 17, $_yclo4k - 9,  9204268) != 0)
         LCLICK($_xclo4k + 1 + RND(-5,5), $_yclo4k + 10 + RND(-5,5))
         $total_num = $total_num + 1
         PRINT("Использован камуфляжный процессор: ", $clo4k_type, " | ", "Всего использованно: ", $total_num)
         $time_camouflage = $_time_t + 1
         $search_clo4k = 1
      END_IF
   END_SWITCH
END_IF
« Last Edit: February 08, 2019, 05:43:29 PM by Космич »
«Иногда ты ваяешь до тех пор, пока до тебя не дойдёт, что именно ты делаешь.»

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
То же самое, без циклов. Таким образом можно "распараллеливать" выполнение скрипта без потоков
Code: (clickermann) [Select]
IF($camouflage != 0 & $time_camouflage < $_time_t)

Неверный синтаксис
Верно так
Code: (clickermann) [Select]
IF(($camouflage != 0) & ($time_camouflage < $_time_t))

ya12

  • Активный участник
  • ***
  • Posts: 165
    • View Profile
В начале так и было, потом код стал слишком большим, мне надоело считать задержки и я перешел на потоки.
Не забываем про рандомные задержки при нажатии клавы и мышки. При этом раз в 20 минут нужно вернуться на базу для бафа.
Часть расчетов выполняется в dll, а пока работает dll поток стоит.

Космич

  • Активный участник
  • ***
  • Posts: 265
    • View Profile
Неверный синтаксис

А почему тогда работает и не сообщает об синтаксической ошибке? Или речь идёт о том, что отсутствие скобок не гарантирует порядок проверки условия слева на право?
«Иногда ты ваяешь до тех пор, пока до тебя не дойдёт, что именно ты делаешь.»

Khodorko

  • Зашел в гости
  • *
  • Posts: 7
    • View Profile
Чтение INI файла не приводи к ошибке во время перезаписи.
Code: (clickermann) [Select]
INIWRITE("config.ini", "parname", "1")
INIREAD("config.ini", "parname")

Хочу попробовать сделать через чтение из ini файла, но тут появился вопрос: у меня файл для удобства находится в другой папке, не в той, где лежит программа, так как к нему обращаются сразу несколько скриптов из разных папок. Так вот, как указать путь к этому ini файлу? Пробовал, как в случае с *.txt указать путь
Code: [Select]
INIWRITE(C:\clickermann\command\potok.ini, mousestatus, 1)на что благополучно выбивается ошибка интерпретации строки.

 А в случае такого варианта
 
Code: [Select]
INIWRITE(potok.ini, mousestatus, 1)
всё работает, но мне это не подходит
« Last Edit: February 16, 2019, 01:14:47 PM by Khodorko »

Космич

  • Активный участник
  • ***
  • Posts: 265
    • View Profile
Кавычки забыл
Code: (clickermann) [Select]
INIWRITE("C:\clickermann\command\potok.ini", "mousestatus", 1)
«Иногда ты ваяешь до тех пор, пока до тебя не дойдёт, что именно ты делаешь.»

Khodorko

  • Зашел в гости
  • *
  • Posts: 7
    • View Profile
Кавычки забыл
Code: (clickermann) [Select]
INIWRITE("C:\clickermann\command\potok.ini", "mousestatus", 1)
нет, это не помогает, всё равно эта же ошибка выскакивает
« Last Edit: February 16, 2019, 01:55:40 PM by Khodorko »

Космич

  • Активный участник
  • ***
  • Posts: 265
    • View Profile
Кавычки забыл
Code: (clickermann) [Select]
INIWRITE("C:\clickermann\command\potok.ini", "mousestatus", 1)
нет, это не помогает, всё равно эта же ошибка выскакивает
кавычки всё равно нужны  :D

Перенеси скрипт к ини файлу и создай ярлык на рабочем столе
«Иногда ты ваяешь до тех пор, пока до тебя не дойдёт, что именно ты делаешь.»

Khodorko

  • Зашел в гости
  • *
  • Posts: 7
    • View Profile
Кавычки забыл
Code: (clickermann) [Select]
INIWRITE("C:\clickermann\command\potok.ini", "mousestatus", 1)
нет, это не помогает, всё равно эта же ошибка выскакивает
кавычки всё равно нужны  :D

Перенеси скрипт к ини файлу и создай ярлык на рабочем столе
Не совсем понял, чем это поможет? С ini работает несколько скриптов, и закидывать их все вместе с файлами, с которыми они работают(картинки, другие скрипты) в одну папку - не вариант, будет жуткая мешанина, а так как часть файлов имеют одно и тоже название, это скорее всего приведёт к сбоям в работе. Неужили для ini файла нельзя указать путь, как для txt?