2016-09-28 1 views
0

я реализовал класс Thread в JS похож на класс Thread в .net/C#:блокирование 'Join' метод на html5 WebWorker

function Thread(func) { 
 
    var o = this; 
 
    o.func = func; 
 
} 
 

 
Thread.prototype.Start = function (p, cb) { 
 
    var o = this; 
 

 
    var toClass = {}.toString; 
 
    var wcode = "" + o.func; 
 
    var re = /\((.*?)\)/; 
 
    var rearr = re.exec(wcode)[1].split(","); 
 
    var odta = {}; 
 
    var tobj = []; 
 
    var pstr = ""; 
 
    for (var i = rearr.length - 1; i >= 0; i--) 
 
    { 
 
     odta[rearr[i]] = p ? p[i] : p; 
 
     pstr += rearr[i] + "=" + rearr[0] + ".data." + rearr[i] + ";"; 
 
     if (p && p[i] && (toClass.call(p[i]) == "[object ArrayBuffer]")) { 
 
      // tobj[tobj.length] = p; 
 
      // trace("added arraybuffer"); 
 
     } 
 
    } 
 

 
    wcode = wcode.replace("{", "{" + pstr); 
 
    re = /return ([^;\}]*?)([;\}])/g; 
 
    wcode = wcode.replace(re, "postMessage($1)$2"); 
 
    //trace("re:" + wcode); 
 
    var blob = new Blob(["onmessage = " + wcode ]); 
 
    // Obtain a blob URL reference to our worker 'file'. 
 
    var blobURL = window.URL.createObjectURL(blob); 
 
    var worker = new Worker(blobURL); 
 
    worker.onmessage = function (e) { 
 
     trace("callback from worker " + e.data); 
 
     if (cb) 
 
      cb(e.data); 
 
    }; 
 
    worker.postMessage(odta, tobj); 
 

 

 
};

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

Он должен работать с Chrome & FF (я уже отказался от IE).

Есть ли способ сделать такой блокирующий вызов так же, как метод join .net?

+0

_ "Теперь я хотел бы реализовать 'Join' метод, т. е. дождаться завершения работы веб-мастера (или отправить сообщение о его завершении) »_ Что делает работник? Неужели 'postMessage' не возвращает ожидаемый результат? Что делает метод 'Join'? – guest271314

+0

Метод Join должен ждать завершения рабочих, я бы сделал что-то вроде «for (i = 0; i

+0

После того, как все вызовы postMessage появились из рабочих потоков? – guest271314

ответ

0

Вы можете использовать Promise конструктор, Promise.all()

function handleWorker(/* args */) { 
    return new Promise((resolve, reject) => { 
    // create worker, do stuff 
    worker.onmessage = function(e) { 
     resolve(/* optionally pass a value */) 
    } 
    worker.onerror = function(err) { 
     reject(err) 
    } 
    }) 
} 

var workers = []; 

for (var i = 0; i < 4; i++) { 
    workers.push(handleWorkers(/* arg */)) 
} 

Promise.all(workers) 
.then(res => console.log("all workers have posted message", res)); 
// handle error 
.catch(function(workerError) { 
    console.log(workerError) 
}); 

jsfiddle https://jsfiddle.net/yo8r3fzw/

0

Как я уже разрабатывало multhreading JS API, поддерживающий параллельное программирование (OODK-JS) Я мог бы дать это прямой ответ:

невозможно заблокировать поток, ожидающий сигнала, поступающего из другого потока.

Почему?

потому что webworkers общаются с главным потоком путем обмена сообщениями. Хорошей попыткой будет реализация бесконечного цикла в основном потоке и установка в качестве условия остановки переменной, которая будет обновляться, когда основной поток получил сообщение от веб-мастера, чтобы разбить цикл. К сожалению, поскольку основной поток зацикливается, сообщения от веб-мастеров не принимаются до тех пор, пока цикл не будет выполнен, так как основной поток продолжает циклически прерываться.

Решение?

Блокировка основной нити невозможна, но все же можно активировать действие, когда все веб-камеры завершили свое задание, выполнив счетчик, увеличивающийся каждый раз, когда веб-мастер отправляет сообщение «task.done», например. После того, как счетчик достиг количества инициализированных веб-мастеров, может быть активировано действие

+0

Запуск действия/функция - это то, чего я пытался избежать, я хотел бы продолжить в той же функции, которая вызывает метод Join. Я начинаю думать, что это будет принятый ответ, хотя ... –

+0

Я объективно думаю, что веб-рабочий был разработан для выполнения задач, которые основной поток не смог выполнить без значительного влияния на пользовательский интерфейс. Все еще расширенные концепции как блокировки, параллельные вызовы, синхронизация свойств объектов могут быть реализованы посредством обмена сообщениями (т. Е. Реализация очереди задач, следующих за шаблоном проектирования производителя/потребителя, достижимой) для имитации стандартной среды mutli-threading – OBDM

0

Я пробовал предложение guest271314, но еще не было, надеялся, что статический Promise.resolve будет блокироваться, поскольку в документации говорится, что он возвращает ' решила "обещание. Вот то, что я до сих пор:

function Thread(func) { 
 
    var o = this; 
 
    o.func = func; 
 
} 
 

 
Thread.prototype.Start = function (p, cb) { 
 
    var o = this; 
 

 
    var toClass = {}.toString; 
 
    var wcode = "" + o.func; 
 
    trace(wcode); 
 
    var re = /\((.*?)\)/; 
 
    var rearr = re.exec(wcode)[1].split(","); 
 
    var odta = {}; 
 
    var tobj = []; 
 
    var pstr = ""; 
 
    for (var i = rearr.length - 1; i >= 0; i--) 
 
    { 
 
     odta[rearr[i]] = p ? p[i] : p; 
 
     pstr += rearr[i] + "=" + rearr[0] + ".data." + rearr[i] + ";"; 
 
     if (p && p[i] && (toClass.call(p[i]) == "[object ArrayBuffer]")) { 
 
      tobj[tobj.length] = p[i]; 
 
      // trace("added arraybuffer"); 
 
     } 
 
    } 
 

 
    wcode = wcode.replace("{", "{" + pstr); 
 
    re = /return ([^;\}]*?)([;\}])/g; 
 
    wcode = wcode.replace(re, "postMessage($1);return;$2"); 
 
    //trace("re:" + wcode); 
 
    var blob = new Blob(["onmessage = " + wcode ]); 
 
    // Obtain a blob URL reference to our worker 'file'. 
 
    var blobURL = window.URL.createObjectURL(blob); 
 
    var worker = new Worker(blobURL); 
 

 
    o.promise = new Promise(function(resolve, reject) { 
 
     worker.onmessage = function (e) { 
 
      trace("callback from worker " + e.data); 
 
      if (cb) 
 
       cb(e.data); 
 
      resolve(); 
 
     }; 
 
    }); 
 
    worker.postMessage(odta, tobj); 
 
}; 
 

 
Thread.prototype.Join = function() { 
 
    var o = this; 
 
    Promise.resolve(o.promise); 
 
    // I'd like to get here AFTER the worker has finished 
 
};

и тестирование его:

var t = new Thread(myfunction); 
 
t.Start([1, 2, 3, new ArrayBuffer(2)]); 
 
t.Join(); 
 
trace("Thread done!");

+0

_ "// I ' d хотел бы получить здесь ПОСЛЕ завершения работника _ _ Использовать '.then()' прикованный к 'Promise.resolve (o.promise);'. Вы также можете «возвращать» 'Promise.resolve (o.promise);' из 't.Join()' вызывать и связывать другой '.then()' с 't.Join()' с 'trace()' call внутри функции '.then()'; для 'trace()', который вызывается после 't.Join()'. 'Thread.prototype.Join = function() { var o = this; return Promise.resolve (o.promise) .then (function() {// эта часть завершена}); // Я хочу получить здесь ПОСЛЕ завершения работника }; ',' t.Join(). Then (function() {trace ("Thread done!")}) ' – guest271314