JavaScript асинхронный против C # асинхронный - PullRequest
1 голос
/ 23 мая 2019

РЕДАКТИРОВАТЬ : нашел ответ - https://www.youtube.com/watch?v=8aGhZQkoFbQ

_

Хорошо, поэтому у меня есть некоторый фон C #, и C # "асинхронная среда" немногосмешанный пакет параллелизма и « малый параллелизм », т. е. когда речь идет о тяжелой асинхронной среде, вы можете иметь условия гонки, тупик и вам необходимо защищать общие ресурсы.

Теперь я пытаюсь понять, как работает асинхронная среда JavaScript / ES6.Рассмотрим следующий код:

// current context: background "page"
// independent from content page
let busy = false;

// This is an event handler that receives event from content page
// It can happen at any time
runtimeObj.onMessage.addListener((request) =>
{
    if(request.action === 'AddEntry')
    {
        AddEntry(request);
        return true;
    }
    return false;
} );


function AddEntry(data)
{
    if (!busy)
        group.push({url: data.url, time: Date.now(), session: data.session});
    else
        setTimeout(AddEntry(data),10000) // simulating Semaphore wait
}

// called from asynchronous function setInterval()
function SendPOST()
{
    if (groups.length < 1 || groups === undefined)
        return;

    busy = true; // JS has no semaphores so I "simulate it"
    let del = [];
    groups.forEach(item =>
    {
        if (Date.now() - item.time > 3600000)
        {
            del.push(item);
            let xhr = new XMLHttpRequest();
            let data = new FormData();
            data.append('action', 'leave');
            data.append('sessionID', item.session);
            xhr.withCredentials = true;
            http.onreadystatechange = function()
            {
                if(http.readyState == 4 && http.status !== 200) {
                    console.log(`Unable to part group ${item.url}! Reason: ${http.status}. Leave group manually.`)
            }
}
            xhr.open('POST', item.url, true);
            xhr.send(data);
        }
    });
    del.forEach(item => groups.slice(item,1));
    busy = false;
}


setInterval(SendPOST, 60000);

Это на самом деле не лучший пример, так как в нем нет набора асинхронных ключевых слов в паре с функциями, но, на мой взгляд, и sendPost(), и AddEntry() не являются действительно чистыми последовательными операциями.,Тем не менее, мне сказали, что в AddEntry(), busy всегда будет false, потому что:

sendPost ставится в очередь для выполнения в минуту

событиедобавить в цикл событий

событие обрабатывается и AddEntry вызывается

, так как busy = false, группа выталкивается

проходит минута и SendPost добавляется в цикл событий

событие является процессом, и SendPost называется

groups.length === 1, поэтому оно продолжается

busy = true

каждая группа вызывает запросчтобы получить в очередь

событие приходит в

busy = false

событие обрабатывается, AddEntry вызывается

busy = false, как всегдаbe

группа выталкивается

, в конце концов, запросы из ранее разрешаются, и обратные вызовы onreadystatechange помещаются в цикл обработки событий

, в конце концов каждый из обратных вызовов обрабатывается иоператоры журнала выполняются

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

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

1 Ответ

2 голосов
/ 23 мая 2019

Это правильно?

Да, он адекватно описывает происходящее.

JS работает однопоточным образом, что означает, что функция всегда будет работать до конца.

 setTimeout(function concurrently() {
   console.log("this will never run");
 });

  while(true) console.log("because this is blocking the only thread JS has");

не может быть условий гонки ...

Может (логическим путем).Однако они не могут появляться в синхронном коде, так как JavaScript выполняется однопоточным¹.Если вы добавите обратный вызов к чему-либо или await обещание, тогда другой код может работать в Тем временем (но никогда в то же время! ), что может вызвать гонкуусловие:

 let block = false;

 async function run() {
   if(block) return // only run this once
   // If we'd do block = true here, this would be totally safe
   await Promise.resolve(); // things might get out of track here
   block = true;
   console.log("whats going on?");
}

run(); run();

... ни тупиков ...

Да, они совершенно невозможны (кроме случаев использования Atomics At).

Мне никогда не нужно защищать общий ресурс.

Да.Поскольку нет общих ресурсов (хорошо, кроме SharedBuffers¹).


¹: Используя WebWorkers (или потоки на NodeJS), вы фактически управляете несколькими потоками JS.Однако каждый поток выполняет свой собственный код JS, поэтому переменные не являются общими.Эти потоки могут передавать сообщения между собой, а также могут совместно использовать определенную конструкцию памяти (a SharedArrayBuffer ).Затем к нему можно получить доступ одновременно, и все эффекты одновременного доступа применяются (но вы будете редко его использовать, так что ...).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...