Я могу все еще разработать 32-разрядные приложения с помощью 64-разрядной машины?

Я перебираю решение в течение дня, но все еще думаю, как сохранить цепочку при использовании обратного вызова. Все знакомы с традиционным стилем программирования, в котором код выполняется построчно, синхронно. SetTimeout использует обратный вызов, поэтому следующая строка не ожидает его завершения. Это позволило мне подумать, как сделать его "синхронизированным", чтобы сделать функцию "сна".

Начиная с простой сопрограммы:

function coroutine() {
    console.log('coroutine-1:start');
    sleepFor(3000); //sleep for 3 seconds here
    console.log('coroutine-2:complete');
}

Я хочу поспать 3 секунды посередине, но не хочу доминировать над всем потоком, поэтому сопрограмма должна выполняться другим потоком. Я рассматриваю Unity YieldInstruction и изменяю сопрограмму следующим образом:

function coroutine1() {
    this.a = 100;
    console.log('coroutine1-1:start');
    return sleepFor(3000).yield; // sleep for 3 seconds here
    console.log('coroutine1-2:complete');
    this.a++;
}

var c1 = new coroutine1();

Объявите прототип sleepFor:

sleepFor = function(ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?sleepFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    setTimeout(function() {
        new Function(funcArgs, funcBody).apply(context, args);
    }, ms);
    return this;
}

После запуска сопрограммы1 (я проверил в IE11 и Chrome49) вы увидите, что он спит 3 секунды между двумя операторами консоли. Он сохраняет коды так же красиво, как и традиционный стиль. Хитрость во сне для рутины. Он читает тело функции вызывающей стороны как строку и разбивает его на 2 части. Снимите верхнюю часть и создайте другую функцию нижней частью. После ожидания указанного количества миллисекунд он вызывает созданную функцию, применяя исходный контекст и аргументы. Для оригинального потока это закончится "возвращением" как обычно. За "доходность"? Он используется для сопоставления регулярных выражений. Это необходимо, но бесполезно.

1116 Это не на все 100% идеально, но, по крайней мере, оно достигает моей работы. Я должен упомянуть некоторые ограничения в использовании этой части кода. Поскольку код разбивается на 2 части, оператор return должен быть во внешнем, а не в любом цикле или {}. т.е.

function coroutine3() {
    this.a = 100;
    console.log('coroutine3-1:start');
    if(true) {
        return sleepFor(3000).yield;
    } // <- raise exception here
    console.log('coroutine3-2:complete');
    this.a++;
}

Приведенные выше коды должны иметь проблему, поскольку закрывающая скобка не может существовать отдельно в созданной функции. Другое ограничение - все локальные переменные, объявленные как "var xxx = 123", не могут быть перенесены в следующую функцию. Вы должны использовать «this.xxx = 123» для достижения того же. Если у вашей функции есть аргументы, и они получили изменения, измененное значение также не может быть перенесено в следующую функцию.

function coroutine4(x) { // assume x=abc
    var z = x;
    x = 'def';
    console.log('coroutine4-1:start' + z + x); //z=abc, x=def
    return sleepFor(3000).yield;
    console.log('coroutine4-2:' + z + x); //z=undefined, x=abc
}

Я бы представил еще один прототип функции: waitFor

waitFor = function(check, ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?waitFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    var thread = setInterval(function() {
        if(check()) {
            clearInterval(thread);
            new Function(funcArgs, funcBody).apply(context, args);
        }
    }, ms?ms:100);
    return this;
}

Он ожидает функцию «check», пока не вернет true. Он проверяет значение каждые 100 мс. Вы можете настроить его, передав дополнительный аргумент. Рассмотрим тестирование coroutine2:

function coroutine2(c) {
    /* some codes here */
    this.a = 1;
    console.log('coroutine2-1:' + this.a++);
    return sleepFor(500).yield;

    /* next */
    console.log('coroutine2-2:' + this.a++);
    console.log('coroutine2-2:waitFor c.a>100:' + c.a);
    return waitFor(function() {
        return c.a>100;
    }).yield;

    /* the rest of code */
    console.log('coroutine2-3:' + this.a++);
}

Также в красивом стиле, который мы любим до сих пор. На самом деле я ненавижу вложенный обратный вызов. Легко понять, что сопрограмма2 будет ждать завершения сопрограммы1. Интересно? Хорошо, затем запустите следующие коды:

this.a = 10;
console.log('outer-1:' + this.a++);
var c1 = new coroutine1();
var c2 = new coroutine2(c1);
console.log('outer-2:' + this.a++);

Вывод:

outer-1:10
coroutine1-1:start
coroutine2-1:1
outer-2:11
coroutine2-2:2
coroutine2-2:waitFor c.a>100:100
coroutine1-2:complete
coroutine2-3:3

Наружное завершение сразу же после инициализированных сопрограмм1 и сопрограмм2. Затем coroutine1 будет ждать 3000 мс. Coroutine2 войдет в шаг 2 после ожидания 500 мс. После этого он продолжит шаг 3, как только обнаружит значения coroutine1.a> 100.

Остерегайтесь того, что есть 3 контекста для хранения переменной «a». Один является внешним, значения которого равны 10 и 11. Другой находится в coroutine1, значения которого равны 100 и 101. Последний находится в coroutine2, значения которого равны 1,2 и 3. В coroutine2 он также ожидает ca, который приходит от coroutine1, пока его значение не станет больше 100. 3 контекста являются независимыми.

Весь код для копирования и вставки:

sleepFor = function(ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?sleepFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    setTimeout(function() {
        new Function(funcArgs, funcBody).apply(context, args);
    }, ms);
    return this;
}

waitFor = function(check, ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?waitFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    var thread = setInterval(function() {
        if(check()) {
            clearInterval(thread);
            new Function(funcArgs, funcBody).apply(context, args);
        }
    }, ms?ms:100);
    return this;
}

function coroutine1() {
    this.a = 100;
    console.log('coroutine1-1:start');
    return sleepFor(3000).yield;
    console.log('coroutine1-2:complete');
    this.a++;
}

function coroutine2(c) {
    /* some codes here */
    this.a = 1;
    console.log('coroutine2-1:' + this.a++);
    return sleepFor(500).yield;

    /* next */
    console.log('coroutine2-2:' + this.a++);
    console.log('coroutine2-2:waitFor c.a>100:' + c.a);
    return waitFor(function() {
        return c.a>100;
    }).yield;

    /* the rest of code */
    console.log('coroutine2-3:' + this.a++);
}

this.a = 10;
console.log('outer-1:' + this.a++);
var c1 = new coroutine1();
var c2 = new coroutine2(c1);
console.log('outer-2:' + this.a++);

Он протестирован в IE11 и Chrome49. Поскольку он использует arguments.callee, это может вызвать проблемы, если он работает в строгом режиме.

19
задан Johan 24 June 2009 в 05:05
поделиться

5 ответов

64-разрядная Windows прекрасно работает с 32-разрядной Visual Studio. Если вы не укажете, что хотите использовать инструменты разработки x64, он по-прежнему будет компилировать 32-разрядные приложения.

Прямо со страницы:

Visual Studio использует 32-разрядный кросс компилятор даже на 64-битной Windows компьютер. Однако вы можете использовать devenv команды для создания командной строки среда для вызова 64-битной размещенной инструменты.

Дополнительная информация: http://msdn.microsoft.com/en-us/library/ms246588 (VS.80) .aspx

18
ответ дан 30 November 2019 в 03:34
поделиться

С Visual Studio вы можете выбрать платформу. По умолчанию он будет работать на «любом процессоре» (32- или 64-разрядный), но вы можете указать, если хотите. В разделе «Проект»> «Свойства»> «Сборка» найдите свойство «Целевая платформа».

10
ответ дан 30 November 2019 в 03:34
поделиться

Да. 64-битная перспектива будет запускать 32-битные исполняемые файлы, поэтому, если у вас есть 32-битный компилятор, он все равно будет работать.

5
ответ дан 30 November 2019 в 03:34
поделиться

В Visual Studio вы можете указать, что нужно компилировать в диспетчере конфигураций - (Меню сборки - Диспетчер конфигурации) - это позволяет выбрать 32- или 64-разрядную версию.

3
ответ дан 30 November 2019 в 03:34
поделиться

64-битное потребительское оборудование обычно представляет собой архитектуру amd64, которая может запускать как 32-битные приложения, так и 64-битные приложения. 64-разрядная версия Windows Vista поддерживает как 32-разрядные, так и 64-разрядные системные библиотеки, поэтому в основном вы можете запускать приложения обоих типов. (Обратите внимание, что архитектура IA-64 не допускает этого.)

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

Как многие упоминали выше, VS2008 позволяет вам выбирать целевую архитектуру, поэтому нет никаких проблем.

1
ответ дан 30 November 2019 в 03:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: