Цитата:
Цитата:
А так остается только приспосабливаться к особенностям языка. |
Мнэээ... наткнулся тут на эту тему. И чисто для справки тем кто как и я будут читать архив, вставлю, что я пока в JavaScript не большой специалист, но в Delphi тоже можно передавать функции как параметры - по ссылке, и возвращать как результат работы. Более того, есть даже возможность описывать типы как функции. Например можно сделать массив или список функций.
И еще - почитал тут в инете, что вроде можно в JavaScript использовать window.postMessage, так что какая-никакая обработка сообщений в нем есть и соответственно это касается вопроса топикстартера. Он не про многопоточность спрашивал, а про передачу управления в очередь обработки сообщений, пока происходит ожидание - заметьте, что это именно в однопоточном приложении. И насколько я понял - если пользоваться очередью сообщений, написав свой ProcessMessages, то только в IE скрипт будет блокироваться, а в других браузерах будет работать асинхронно. |
Извините, но в выложенных примерах пока никак не разобрался, может быть, позднее разберусь, когда прочту весь учебник.
Очень хотелось бы сделать, чтобы браузер не зависал при длительном вычислении, то есть чтобы рекурсивная функция длительного перебора не препятствовала другим процессам. Очень хотелось бы найти аналог Application.ProcessMessages в javascript, который позволял бы, например, идти часам во время работы программы. Браузер Firefox зависнет на целую минуту в Судоку-онлайн для примера 3, пока программа сделает 3 миллиона переборов, а в для примера 46 зависнет на целых 2 минуты, пока программа сделает 9 миллионов переборов. Вот здесь добавил часы на страничку sudokut.htm , и если вы попробуете решить пример 3 или пример 46, то увидите, что во время работы программы часы остановятся. Скрипт программы. Подвешивает браузер вот этот код. function recfrugal(k) { var i; var j; var t; var q; if (k == 82) { u++; for (i = 1; i <= 81; i++) z[i][u] = s[i] } if ((k <= 81) && (u < 10)) { if ((w[k] == 0) || (w[k] == 1)) recfrugal(k+1); if (w[k] > 1) { for (t = 1; t <= w[k]; t++) { q = true; for (j = 1; j <= 20; j++) if (b[k][t] == s[m[k][j]]) q = false; if (q == true) { s[k] = b[k][t]; c++; recfrugal(k+1); } } s[k] = 0; c++; } } } Что конкретно надо добавить в код программы, чтобы зависание браузера во время длительных вычислений не происходило? В Паскале (Лазарусе) достаточно было для этого дописать в код функции одну только строчку Application.ProcessMessages Цитата:
|
JS однопоточный язык. Нет в нём изначально никаких "других" процессов. Остановка - есть остановка всего на странице.
Современное решение: web worker. Он создаёт отдельный поток из отдельного скрипта, что общается с основным потоком сообщениями. По старинке: дробить вычисления setTimeout'ами. |
Я как раз сейчас этим занимаюсь в рамках Collection 5.2 (в сообщение по ссылке есть ссылка на демо видео, где создано 50 потоков с разными приоритетами, каждый из которых считает 1кк итераций), где потоки реализуются с помощью прерываний (yield) функций и планировщика, т.е. модель такая же как и в потоках на одноядерных процах.
Цитата:
|
Цитата:
То что делаешь ты - крутотень, но весьма специфическая.) |
Цитата:
// Простая синхронная итерация $C([...]).forEach(function () { ... }); // Итерация в потоке $C([...]).forEach(function () { ... }, {thread: true}); Главный плюс таких потоков, что по сути, мы остаёмся в главном потоке и у нас спокойный доступ к DOM, переменным замыкания и т.д. хотя с другой стороны это и минус - т.к. можно выстрелить себе в ногу. К сожалению самый главный недостаток этого подхода - это необходимость поддержки генераторов, а она есть только в Хроме и ФФ, но обещали вкрутить в ИЕ12, а про Сафари я даже не знаю, надо будет посмотреть, но в ноде я уже планирую полноценное внедрение этой технологии. |
Цитата:
Но куда вставлять этот setTimeout, если функция, вызывающая зависание браузера, рекурсивная? function recfrugal(k) { var i; var j; var t; var q; if (k == 82) { u++; for (i = 1; i <= 81; i++) z[i][u] = s[i] } if ((k <= 81) && (u < 10)) { if ((w[k] == 0) || (w[k] == 1)) recfrugal(k+1); if (w[k] > 1) { for (t = 1; t <= w[k]; t++) { q = true; for (j = 1; j <= 20; j++) if (b[k][t] == s[m[k][j]]) q = false; if (q == true) { s[k] = b[k][t]; c++; recfrugal(k+1); } } s[k] = 0; c++; } } } Если заменить рекурсивный вызов recfrugal(k+1); вот так: setTimeout(function() { recfrugal(k+1) }, 1000); то ничего не получается, так как она просто будет через него перескакивать, корректного результата не получится. |
Переписать рекурсию на циклы.
![]() |
Оставлю тут ссылку: реализация потоков в Collection 5.2
|
Часовой пояс GMT +3, время: 07:33. |