Pull to refresh
60
19
Send message

Правильно ли это?

Есть неточности. Вот как правильно:

Task.Run(...) действительно всегда отправляет делегат по маршруту TaskScheduler.DefaultThreadPoolTaskSchedulerThreadPool. И тем самым мы сразу и надёжно отвязываемся от SynchronizationContext.Current.

await DoAsync().ConfigureAwait(false) будет иметь эффект только в случае фактической асинхронности. Например:

await (Task.CompletedTask).ConfigureAwait(false);
Debug.Assert(SynchronizationContext.Current == null); // FAIL

Поэтому ConfigureAwait приходится дописывать каждый раз, к каждому await.

И с терминологией важно не путаться:

  • SynchronizationContext - контекст синхронизации - планировщик, в который отправляются await continuations.

  • ExecutionContext - контекст выполнения - место хранения async locals.

Приостанавливает (suspend) означает, что метод (сопрограмма) подписывает себя на асинхронное продолжение (continuation) и выходит (делает return), освобождая поток.

Синхронный код ждёт, занимая/блокируя поток через busy wait или примитивы синхронизации ОС.

Скорее всего, вы имеете в виду отсутствие параллелизма в пределах метода (типа WhenAll или ForAsync). От этого ни сам метод, ни дочерние вызовы не перестают быть асинхронными. Хронологически, между Read и Write может успеть выполниться часть другого асинхронного метода. Другими словами, может случиться кооперативная многозадачность на уровне приложения (как раз то, зачем придумали async/await).

гораздо эффективнее и проще вызвать аналогичную синхронную функцию

Я бы не рискнул давать такой совет хотя бы потому, что мы не знаем конкретного call-стека. В контексте статьи спорить не о чем - здесь код лишь иллюстрирует преобразование компилятора.

  1. Цель - "понять, как работает async/await" (это написано в заголовке статьи).

  2. Вы пишете про самый первый пример: "зачем-то асинхронные функции вызываются синхронно". Но ведь это не так. В нём асинхронно вызываются асинхронные функции - await File.XxxAllTextAsync.

И правда, моя формулировка получилась слишком общей. Добавил уточнение:

"само по себе преобразование async-метода в стейт-машину не приводит к запуску потока"

Магия async/await (то есть преобразование кода, проводимое компилятором) никогда не создаёт потоки сама. Она только комбинирует результаты других вызовов через GetAwaiter и AsyncXXXMethodBuilder. При этом даже тип Task не обязателен - см. Generalized async return types and ValueTask.

Это похоже на оверинжиниринг.

Зато легко отлаживать. Вначале я запускал этот тул на локальной машине, долго гонял и наблюдал, а потом уже пересадил в облако. Легко добавлять любые дополнительные условия и костыли.

… разве отсутствует в Mercurial?

Здесь я имею в виду не сами концепции пулл-реквестов и ревью, а то как они реализованы в гитхабовском UI.


Были ли еще какие-то причины? Потому, что сейчас мне видится только бесплатная разработка/поддержка со стороны пользователей GitHub этого набора компонентов.

Вклад со стороны сообщества — не главная причина. В CONTRIBUTING мы честно говорим, что не обещаем принимать каждый PR. В первую очередь, мы хотим стать ближе к frontend-разработчикам, дать пользователям возможность получать фиксы и новые фичи, не дожидаясь официальных релизов (в идеале, прийти к continuous delivery). Для DevExtreme же, как для продукта, это бесценная быстрая обратная связь.

Да, так ещё лучше. И теперь можно убрать проверку перед echo, т.к. обходятся только запущенные контейнеры.
baseimage-docker не советую! Объясню почему:
  1. runit, используемый в качестве менеджера процессов, очень неудобен в использовании, особенно когда что-то идёт не так. Supervisord куда более приятен и к тому же сам умеет делать «reape unknown pid», так что «изобретения» в виде my_init не нужны.
  2. Ни ssh, ни nsenter теперь не являются необходимыми. Для входа в контейнер используется команда docker exec -ti CONTAINER_ID bash. Для более удобной работы в консоли внутри контейнера (запуск mc и тп.) рекомендую добавить в Dockerfile:
    ENV LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 TERM=xterm
    RUN locale-gen $LC_ALL
  3. Самое опасное: cron и logrotate пускаются со стандартными конфигами, не рассчитанными на работу в контейнерах. Пример: установили Apache, получили файл /etc/logrotate.d/apache2, внутри которого используется /etc/init.d, значит runit потеряет контроль над процессом после первой ротации логов.
Тих, никуда не пишет.
В качестве более легковесной альтернативы для контейнеров в пределах одного хоста хочу посоветовать обычный dnsmasq.

После установки создайте файл /etc/dnsmasq.d/docker с контентом

addn-hosts=/docker-container-hosts
interface=docker0

Теперь после добавления нового контейнера или пересоздания/перезапуска существующего надо будет выполнить примерно такой скрипт:

Код
#!/bin/bash

# виртуальный домен для контейнеров
DOMAIN=containers.example.com

# addn-hosts файл для dnsmasq
CONTAINER_HOSTS=/docker-container-hosts

echo "# Auto-generated by $0" > $CONTAINER_HOSTS
for CONTAINER in тут список имен ваших контейнеров; do
    IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' $CONTAINER)
    [ $IP ] && echo "$IP  $CONTAINER.$DOMAIN" >> $CONTAINER_HOSTS
done

# просим dnsmasq перечитать CONTAINER_HOSTS
pkill -x -HUP dnsmasq


Минусы:
  1. нужно явно перечислять имена контейнеров
  2. нужно не забывать запускать скрипт (хотя вокруг этого всего несложно сделать обвязку)

Плюсы:
  1. не нужны дополнительные контейнеры
  2. используется стабильный софт
  3. мгновенное обновление (TTL=0)

Идея взята отсюда.
Из Ростелекома пакеты тоже идут через Японию:
tracert
  1     3 ms     2 ms     2 ms  
  2    27 ms    26 ms    26 ms  
  3    33 ms    28 ms    28 ms  
  4    30 ms    31 ms    27 ms  
  5    33 ms    31 ms    32 ms  77.51.254.234
  6    90 ms    74 ms    74 ms  ae-5.626.m7-cr1-b.msk.ip.rostelecom.ru [188.254.36.101]
  7   133 ms   144 ms   136 ms  95.167.91.155
  8   174 ms   162 ms   166 ms  61.213.146.253
  9   185 ms   185 ms   162 ms  ae-0.r23.tokyjp01.jp.bb.gin.ntt.net [129.250.4.106]
 10   236 ms   232 ms   231 ms  as-6.r21.sngpsi02.sg.bb.gin.ntt.net [129.250.5.157]
 11   233 ms   225 ms   241 ms  ae-4.r20.sngpsi02.sg.bb.gin.ntt.net [129.250.6.100]
 12   227 ms   226 ms   228 ms  116.51.27.150
 13   299 ms   226 ms   225 ms  103.253.144.242
 14   246 ms   254 ms   246 ms  128.199.244.8

Ping statistics for 128.199.244.8:
    Minimum = 247ms, Maximum = 251ms, Average = 249ms
Утечка спектра — вполне признанный термин. Хорошо демонстрирует границы применимости теоремы Котельникова.

Сигнал ограничен во времени => спектр растекается (см. Benedicks's theorem). Спектр растекается => невозможно применить теорему Котельникова.
Автор хотел более доходчиво донести «физику явления». А формулы и их выводы можно в книжках посмотреть. Мне, например, очень понравилась часть статьи, где объясняется, почему применение окон приводит к растеканию спектра.
Раздел с PDF-ами доступен, но не уверен, что в них есть ответ на мой вопрос. Интересует документация в духе такой или такой.

Там легко понять, что для Chrome Store нужно загрузить zip c иконкой и манифестом, а для Firefox Marketplace просто указать ссылку на .webapp-файл. Что делать для Tizen? В панели разработчика просят загрузить абстрактный Binary File.

Уточню: интересуют именно hosted web-приложения.
Есть ли хотя бы минимальный туториал о том, как опубликовать hosted-приложение в store? Гугление по «tizen hosted applications» не дает практически ничего.
Цель демки Kitchen Sink — показать доступный арсенал UI-элементов, а не производительность. В плане производительности же, скажем прямо, есть куда копать.
Продукт будет развиваться, и с выходом новых версий будет обновляться идущий в комплекте jQuery. В своем проекте разработчик может подложить версию поновее самостоятельно, главное не напороться на несовместимости (например, мы знаем что не всякая версия Knockout совместима с jQuery)
1

Information

Rating
283-rd
Registered
Activity