Страницы

Поиск по вопросам

четверг, 31 января 2019 г.

Как получить местное время из серверного?

На локальной машине функция DateTime.Now.ToString() дает результат
27.06.2016 15:27:55
, а при развертывании на сервер
6/28/2016 1:14:55 AM
Как привести второй вариант в первому? Желательно без разбора строк.


Ответ

DateTime.Now.ToString(CultureInfo.GetCultureInfo("ru-ru"))
Класс CultureInfo находится в пространстве имен System.Globalization
Если получение строкового представления даты вызывается многократно в разных местах, и каждый раз явно указывать язык неудобно, то можно установить локаль в рамках всего треда:
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("ru-ru");

Если сервер находится в другом часовом поясе, а дату нужно получить, например, по московскому времени, то воспользуйтесь классом TimeZoneInfo
static string GetCurrentDateTime() { var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"); return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz) .ToString(CultureInfo.GetCultureInfo("ru-ru")); }
Список идентификаторов часовых поясов можно получить, вызвав TimeZoneInfo.GetSystemTimeZones()

Как вставить текст в скрытый textarea с помощью selenium webdriver

День добрый. Каким образом можно вставить текст в скрытый элемент Textarea с помощью Selenium Webdriver


Ответ

Dim txtScript = String.Format("arguments[0].innerText = '{0}';", "texttexttext") DirectCast(driver, IJavaScriptExecutor).ExecuteScript(txtScript, element)

Почему файл не добавляется в .gitignore? [дубликат]

На данный вопрос уже ответили: Не игнорируются файлы в .gitignore 2 ответа Я составил .gitignore файл положил его в корень проекта в файле есть указание на то что нужно игнорировать файлы типа .idea/workspace.xml
# Intellij *.iml .idea/workspace.xml .idea/libraries
Но все равно когда пишу git status получаю
Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory)
modified: .idea/workspace.xml
Что делаю не так?


Ответ

Строка
modified: .idea/workspace.xml
говорит что офайл уже в индексе, это значит что его для начала нужно перестать отслеживать
git rm --cached .idea/workspace.xml
GIT rm
после этого если файл правильно добавлен в gitignore то при команде
git status
файла не доолжно быть
Добавление gitignore
git add .gitignore git commit -m"gitignore was updated" gut push origin master

Не выводит случайное число в PHP

В чем разница volatile и static?

Если я правильно понял, то static хранит только последнее записанное в него значение, без разницы сколько потоков обращаются к этой переменной, каждый кто обратиться к ней получит последнее записанное значение.
А volatile в свою очередь создается с новым созданным объектом и при обращении к ней из разных потоков он возвращает самое свежее значение своего объекта.
Запутанно объяснил наверное, но вот как то так я понял...
Не знаю насколько принципиальная разница...


Ответ

volatile означает, что чтение и запись переменной с данным квалификатором является атомарной операцией, при этом любое изменение такой переменной будет видно из других потоков.
static никак не связано с многопоточностью, этот модификатор указывает, что переменная не принадлежит объекту, она ассоциирована с классом/интерфейсом. Операции над static-переменными не являются потокобезопасными. При этом каждый поток может работать со своей копией статической переменной (если она не объявлена как volatile) - соответственно без синхронизации изменения в такую переменную могут быть не видны другим потокам.

Java Memory Model и happens-before

Добрый день. Есть небольшой вопрос по JMM. Я знаю как работает happens-before, но не могу понять один момент. Вот код:
private static int x = 0; private static volatile boolean flag = false;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> { x = 10; while (!flag) ; System.out.println(x); }).start();
x = 5; flag = true; }
Какое значение должно принять X? Если какое-то правило чтобы определить это?


Ответ

Если изобразить потоки выполнения в вашем коде, мы получим такую картину:

Main thread - это основной поток вашей программы, Thread1 - поток, который вы явно создаете.
Запись и чтение волатильной переменной flag действительно создают отношение Happens-Before (E → B на диаграмме). Таким образом по отношению к вызову System.out.println(x); у нас есть два потока выполнения, для каждого из которых гарантируется порядок выполнения: A → B → C и D → E → B → C. Запись в переменную x произойдет гарантированно раньше ее чтения.
Но вот инструкции записи в переменную x (A и D) находятся в состоянии гонки (race condition) и их порядок выполнения друг относительно друга не определен. В итоге то, что мы видим на диаграмме никак нельзя назвать полным порядком. JVM вполне может выполнить инструкции следующим образом:

Вопрос касательно методов Ruby

В чем разница между методами map и collect?
Подскажите плиз когда использовать map, а когда collect?


Ответ

Абсолютно никакой разницы.
Исходники этих методов указывают в один и тот же код на Си. (для массивов они реализованы на Си отдельно, но тоже одинаково)
Проверьте сами, установив и запустив pry и сделав на интересующем объекте obj
show-source obj.collect show-source obj.map

Что использовать — холивар
Есть лица, считающие, что надо использовать их так, чтобы код хорошо читался. В этом контексте обычно лучше работает collect (собрать), как "собрать результаты выполнения блока для каждого элемента". Есть лица, считающие, что надо всегда использовать map, потому что это широко известная (вне Ruby) операция преобразования данных, в которой каждый элемент коллекции преобразуется независимо от остальных. Есть лица, жалеющие, что в Ruby так много синонимов и потому так много споров о чисто косметических вещах (bikeshedding).
collect_concat vs. flat_map reduce vs. inject detect vs. find find_all vs. select include? vs. member?

Как увеличивать значение style.left?

function right() { square.style.left += 50+'px'; }
Как устанавливать не фиксированное значение в style.left, а прибавлять\отнимать его ?


Ответ

Данное свойство является строкой, поэтому прежде чем увеличивать его, его надо перевести в число, например используя функцию parseInt
function right() { square.style.left = (parseInt(square.style.left,10)+50)+'px'; }
Пример:
var square = document.getElementById('square'); square.onclick = function() { right() } function right() { square.style.left = (parseInt(square.style.left, 10) + 50) + 'px'; } #square { position: absolute; background-color: lime; width: 40px; height: 40px; }


Стоит обратить внимание на то, что свойство left установлено в inline стилях, в противном случае оно будет равно пустой строке, и parseInt(square.style.left, 10) вернет NaN
Другим вариантом, может быть использование функции getComputedStyle, позволяющей получить текущее значение свойства, как значения по умолчанию, в случае, когда inline свойство пустое.
var square = document.getElementById('square'); square.onclick = function() { right() } function right() { square.style.left = (parseInt(square.style.left || getComputedStyle(square)['left'], 10) + 50) + 'px'; } #square { position: absolute; background-color: lime; width: 40px; height: 40px; }

Visual Studio. Отсутствует меню создания ASP.NET проекта

При попытке создания проекта ASP.NET в Visual Studio в пути
ФАЙЛ > Создать > Проект > Веб
отсутствует меню создания проектов ASP.NET. На его месте находится элемент WebTemplate. При создания проекта данного типа (WebTemplate), Visual Studio выдаёт ошибку.
Как должно выглядеть:

Как это у меня выглядит:

Версия Visual Studio Enterprise 2015 Update 3. Web компоненты присутствуют. Пробовал делать Repair (так как Repair от онлайн установщика Visual Studio 2015 Update 3 был недоступен, я использовал версии Update 0).


Ответ

Переустановка Visual Studio помогла решить данную проблему. После удаления, я удалил все директории принадлежащие Visual Studio
Такие как:
C:\Program Files (x86)\Microsoft Visual Studio 11.0 C:\Program Files (x86)\Microsoft Visual Studio 12.0 C:\Program Files (x86)\Microsoft Visual Studio 14.0
Очистил реестр от нерабочих значений, прочистил жесткий диск на файлы .tmp, .old и так далее при помощи утилиты WinTools.net.
На место старой Visual Studio 2015 Update 3 начал установку Visual Studio 2015 [без обновлений], к счастью, установщик сам установил необходимые компоненты и обновления. Сейчас сижу на Visual Studio 2015 Update 3

Арифметика с плавающей точкой

Возникла необходимость перевести секунды в милисекунды. Скрипт:
#!/bin/bash a=$(ffprobe -i c848a39afc54e04cc64ddd955686654b9b1c6f31 -show_entries format=duration -v quiet -of csv="p=0"); b=1000; result=$(($a*$b)); echo $result
Вывод
./sectomilisec: line 4: 23.760000*1000: syntax error: invalid arithmetic operator (error token is ".760000*1000")
Как правильно умножить вывод операции на число?


Ответ

invalid arithmetic operator (error token is ".760000*1000")
в программе bash не реализована арифметика с плавающей точкой (только целочисленная).
для осуществления таких вычислений придётся воспользоваться какой-то другой программой. например, bc
result=$(echo "$a*$b" | bc -l)
или dc
result=$(echo "$a $b + p" | dc)

подробности:
bc: википедия, man bc, info bc dc: википедия, man dc, info dc

кстати, в этом выражении знаки доллара перед именами переменных не нужны:
result=$(($a*$b))
достаточно (и более правильно) так:
result=$((a*b))

Как отличить событие закрытия Activity от поворота экрана?

Как программно отличить событие настоящего закрытия Activity от промежуточных вызовов onStop() и onDestroy() при повороте экрана (изменения ориентации экрана)?


Ответ

Метод boolean isFinishing(). Вызывается обычно в onPause()

Зачем нужны абстрактные классы коллекций помимо интерфейсов?

Почему в Java, кроме интерфейсов коллекций, есть соответствующие им абстрактные классы. Например, есть интерфейс Collection. и абстрактный класс AbstractCollection, List и AbstractList. Почему недостаточно только интерфейса?


Ответ

Абстрактные классы - это helper-классы, предоставляющие базовую умолчательную "скелетную" реализацию функциональности соответствующих интерфейсов. Например, класс AbstractCollection предоставляет пользователю "скелетную" реализацию интерфейса Collection. Для того, чтобы реализовать свою коллекцию, вам нужно просто унаследоваться от AbstractCollection и предоставить свои собственные реализации тех методов, которые специфичны для вашей коллекции. А те, которые неспецифичны - просто унаследуются в готовом виде из AbstractCollection. Таким образом вам не нужно будет писать ворох "скучных" методов с тривиальной или рутинной реализацией.
В то же время вы не обязаны пользоваться AbstractCollection. Вы имеете полное право, если вам так захочется, реализовать интерфейс Collectionсвоими силами, с нуля, не пользуясь услугами AbstractCollection
Точно также проведено разделение между List и AbstractList

Внутренний vs Анонимный vs Отдельный классы

В ходе изучения языка все реже возникают вопросы "Как решить задачу?" и все чаще встает вопрос "Какой способ более правильный с точки зрения хорошего тона программирования?"
К примеру, в ходе написания программы, реализующей возможность ведения складского учета, возник вопрос, какой класс использовать: анонимный, внешний или внутренний? Есть класс главного окна программы, реализующий JDesktopPane. Есть отдельный класс "Каталог товаров", реализующий JInternalFrame. Из последнего, нажатием кнопок, открывается окно Карточки товара" (также класс extends JInternalFrame). В свою очередь кликом по кнопкам он реализует открытие окон выбора группы товара, единицы измерения, категории и т.д. Все это тоже JInternalFrame
Вот теперь стоит вопрос, какой тип класса "эстетичнее" использовать? Логика подсказывает делать все классы ниже "Каталога товаров" вложенными в него, а все слушатели нажатия кнопок - анонимными. Но тогда класс получается под тысячу строк кода, что влияет на читаемость. Или это нормально? В общем я как тот осел, между двумя стогами сена.
Вот, к примеру, такой участок кода. Оптимален ли он, или стоит изменить структуру?
package catalogs; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.beans.PropertyVetoException; import java.io.File; import java.util.ArrayList; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.ListSelectionModel; import javax.swing.event.TableModelListener; import javax.swing.event.TreeModelListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.table.TableModel; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import main.Global;
/** * Класс окна справочника товара. Выводит окно каталога товаров с возможностью добавления/удаления/редактирования групп товаров и самих * товаров. Представляет собой древо групп товаров, таблицу товаров, кнопки добавления/удаления/редактирования. */
public class ProductCatalog extends JInternalFrame{ private static final long serialVersionUID = 1L;
private JDesktopPane mainPane; public JTree treeGroup; private GroupTreeModel treeGroupModel; private JScrollPane treeGroupScrlPane; private JButton btnAddGroup; private JButton btnDelGroup; private JButton btnEditGroup; public JTable tblProduct; public ProdTableModel tblProductModel; private JScrollPane tblProductScrlPane; private JButton btnAddProduct; private JButton btnDelProduct; private JButton btnEditProduct;
/** * Конструктор, принимает ссылку на JDesctopPane главного окна. */ public ProductCatalog(JDesktopPane mainPane){ this.mainPane = mainPane; paintComponents(); }
/** * Метод отрисовки компонент окна. */ private void paintComponents(){ treeGroupModel = new GroupTreeModel(); treeGroup = new JTree(treeGroupModel); treeGroup.setSelectionRow(0); treeGroup.addTreeSelectionListener(new TreeSelectionListener(){ @Override public void valueChanged(TreeSelectionEvent selection) { if(!treeGroup.isSelectionEmpty()){ tblProductModel.buildTable(treeGroup.getLastSelectedPathComponent()); tblProduct.revalidate(); tblProduct.repaint(); } } }); treeGroupScrlPane = new JScrollPane(treeGroup); treeGroupScrlPane.setBounds(10, 10, 150, 260);
btnAddGroup = new JButton(); ImageIcon btnAddGroupIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnAddGroup.png"); btnAddGroup.setIcon(btnAddGroupIcon); btnAddGroup.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { addGroup(); } }); btnAddGroup.setBounds(10, 280, 30, 30); btnDelGroup = new JButton(); ImageIcon btnDelGroupIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnDelGroup.png"); btnDelGroup.setIcon(btnDelGroupIcon); btnDelGroup.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { delGroup(); } }); btnDelGroup.setBounds(50, 280, 30, 30); btnEditGroup = new JButton(); ImageIcon btnEditGroupIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnEditGroup.png"); btnEditGroup.setIcon(btnEditGroupIcon); btnEditGroup.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { editGroup(); } }); btnEditGroup.setBounds(90, 280, 30, 30);
tblProductModel = new ProdTableModel(); tblProduct = new JTable(tblProductModel); tblProductModel.buildTable(treeGroup.getLastSelectedPathComponent()); tblProduct.setAutoCreateRowSorter(true); tblProduct.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); tblProduct.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tblProduct.getColumnModel().getColumn(0).setPreferredWidth(25); tblProduct.getColumnModel().getColumn(1).setPreferredWidth(200); tblProduct.getColumnModel().getColumn(2).setPreferredWidth(25); tblProduct.getColumnModel().getColumn(3).setPreferredWidth(50); tblProductScrlPane = new JScrollPane(tblProduct); tblProductScrlPane.setBounds(170, 10, 500, 260);
btnAddProduct = new JButton(); ImageIcon btnAddProductIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnAddProduct.png"); btnAddProduct.setIcon(btnAddProductIcon); btnAddProduct.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { addProduct(); } }); btnAddProduct.setBounds(170, 280, 30, 30); btnDelProduct = new JButton(); ImageIcon btnDelProductIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnDelProduct.png"); btnDelProduct.setIcon(btnDelProductIcon); btnDelProduct.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { delProduct(); } }); btnDelProduct.setBounds(210, 280, 30, 30); btnEditProduct = new JButton(); ImageIcon btnEditProductIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnEditProduct.png"); btnEditProduct.setIcon(btnEditProductIcon); btnEditProduct.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { editProduct(); } }); btnEditProduct.setBounds(250, 280, 30, 30);
this.setTitle("Каталог товаров"); this.addComponentListener(new ComponentListener(){ @Override public void componentResized(ComponentEvent e) { treeGroupScrlPane.setBounds(10, 10, 150, ProductCatalog.this.getHeight()-87); btnAddGroup.setBounds(10, ProductCatalog.this.getHeight()-67, 30, 30); btnDelGroup.setBounds(50, ProductCatalog.this.getHeight()-67, 30, 30); btnEditGroup.setBounds(90, ProductCatalog.this.getHeight()-67, 30, 30); tblProductScrlPane.setBounds(170, 10, ProductCatalog.this.getWidth()-200, ProductCatalog.this.getHeight()-87); btnAddProduct.setBounds(170, ProductCatalog.this.getHeight()-67, 30, 30); btnDelProduct.setBounds(210, ProductCatalog.this.getHeight()-67, 30, 30); btnEditProduct.setBounds(250, ProductCatalog.this.getHeight()-67, 30, 30); } @Override public void componentHidden(ComponentEvent arg0) {} @Override public void componentMoved(ComponentEvent arg0) {} @Override public void componentShown(ComponentEvent arg0) {} }); this.setClosable(true); this.setMaximizable(true); this.setIconifiable(true); this.setResizable(true); this.getContentPane().setLayout(null); this.setSize(700, 347); this.setVisible(true); this.add(treeGroupScrlPane); this.add(btnAddGroup); this.add(btnDelGroup); this.add(btnEditGroup); this.add(tblProductScrlPane); this.add(btnAddProduct); this.add(btnDelProduct); this.add(btnEditProduct); }
/** * Рекурсивный метод построения массива элементов древа групп товаров. */ ArrayList arr = new ArrayList(); public ArrayList getComboBoxTree(Object parent, String separator){ Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+parent+"'"); for(int i=0; i0) getComboBoxTree(buf[i][0], " "+separator); } return arr; }
/** * Метод, реализующий добавление группы товаров в БД. */ private void addGroup(){ String name = JOptionPane.showInputDialog(null, "Введите название новой подгруппы
в группе \""+ treeGroup.getLastSelectedPathComponent() +"\":", ""); if(name!=null){ Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ name +"'"); if(buf.length==0){ if(name.length()>0){ Object[][] parentGroup = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ treeGroup.getLastSelectedPathComponent() +"'"); Global.sqlQueryVoid("INSERT INTO `prod_group` (`name`, `parent`) VALUES ('"+ name +"', '"+ parentGroup[0][0] +"')"); treeGroup.updateUI(); }else JOptionPane.showMessageDialog(null, "Наименование группы товаров не может быть пустым!", "Ошибка!", JOptionPane.ERROR_MESSAGE); }else JOptionPane.showMessageDialog(null, "Группа товаров с таким наименованием уже существует!", "Ошибка!", JOptionPane.ERROR_MESSAGE); } }
/** * Метод, реализующий удаление группы товаров из БД. */ private void delGroup(){ boolean isEmpty = false; Object[][] buf = Global.sqlQueryResult("SELECT `id` FROM `prod_group` WHERE `name`='"+ treeGroup.getLastSelectedPathComponent() +"'"); Object[][] buf2 = Global.sqlQueryResult("SELECT * FROM `product` WHERE `group`='"+ buf[0][0] +"'"); Object[][] buf3 = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+ buf[0][0] +"'"); if(buf2.length==0 && buf3.length==0) isEmpty = true; if(!treeGroup.getLastSelectedPathComponent().equals(null)){ //Если выделена группа, if(isEmpty){ //она пуста if(JOptionPane.showConfirmDialog(null, "Вы уверены?", "Подтверждение удаления", JOptionPane.YES_NO_OPTION)==0){ //и мы подтверждаем удаление, тогда удаляем. Global.sqlQueryVoid("DELETE FROM `prod_group` WHERE `name`='"+ treeGroup.getLastSelectedPathComponent() +"'"); treeGroup.updateUI(); } }else JOptionPane.showMessageDialog(null, "Нельзя удалить эту папку, т.к. она не пуста!", "Ошибка!", JOptionPane.ERROR_MESSAGE); }else JOptionPane.showMessageDialog(null, "Вы не выбрали ни одну папку!", "Ошибка!", JOptionPane.ERROR_MESSAGE); }
/** * Метод, реализующий редактирование группы товаров в БД. */ private void editGroup(){
if(treeGroup.getSelectionRows()[0] != 0){ //Если выбрана не корневая группа, переименовываем группу товаров. final JInternalFrame ifEditGroup; final JComboBox cbParent; final JLabel lblName; final JTextField tfName; final JButton btnOK; final JButton btnCancel; final ArrayList arr;
ifEditGroup = new JInternalFrame();
JLabel lblParent = new JLabel("Родительская группа:"); lblParent.setBounds(10, 10, 150, 20); cbParent = new JComboBox(); cbParent.setBounds(170, 10, 250, 20); arr = getComboBoxTree(0, ""); for(int i=0; i ifEditGroup.getContentPane().setLayout(null); ifEditGroup.add(lblParent); ifEditGroup.add(cbParent); ifEditGroup.add(lblName); ifEditGroup.add(tfName); ifEditGroup.add(btnOK); ifEditGroup.add(btnCancel); ifEditGroup.setTitle("Редактирование группы товаров"); ifEditGroup.setSize(450, 130); ifEditGroup.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); ifEditGroup.setVisible(true);
boolean isOpened = false; Object[] ifArr = mainPane.getAllFrames(); for(int i=0; i/** * Метод, реализующий добавление товара в БД. */ private void addProduct(){ boolean isOpened = false; Object[] ifArr = mainPane.getAllFrames(); for(int i=0; i/** * Метод, реализующий удаление товара из БД. */ private void delProduct(){ if(JOptionPane.showConfirmDialog(null, "Вы уверены?", "Подтверждение удаления", JOptionPane.YES_NO_OPTION)==0){ String code = ProductCatalog.this.tblProduct.getValueAt(ProductCatalog.this.tblProduct.getSelectedRow(), 0).toString(); Global.sqlQueryVoid("DELETE FROM `product` WHERE `id`='"+code+"'"); Global.sqlQueryVoid("DELETE FROM `prod_barcode` WHERE `prod_id`='"+code+"'"); ProductCatalog.this.tblProductModel.buildTable(ProductCatalog.this.treeGroup.getLastSelectedPathComponent()); ProductCatalog.this.tblProduct.revalidate(); ProductCatalog.this.repaint(); } }
/** * Метод, реализующий редактирование товара в БД. */ private void editProduct(){ boolean isOpened = false; Object[] arr = mainPane.getAllFrames(); for(int i=0; i/** * Модель дерева. */ private class GroupTreeModel implements TreeModel{ @Override public Object getChild(Object parent, int index) { Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ parent +"'"); Object parentCode = buf[0][0]; Object[][] res = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+ parentCode +"'"); return res[index][1]; } @Override public int getChildCount(Object parent) { Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ parent +"'"); Object parentCode = buf[0][0]; Object[][] res = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+ parentCode +"'"); return res.length; } @Override public int getIndexOfChild(Object parent, Object child) { Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ parent +"'"); Object parentCode = buf[0][0]; Object[][] res = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+ parentCode +"'"); int index = 0; for(int i =0; i /** * Модель таблицы. */ public class ProdTableModel implements TableModel{ private Object[][] sample = null;
public void buildTable(Object group){ //Метод построения двумерного массива данных, на основе которого отрисовывается таблица товаров. Object[][] buf = Global.sqlQueryResult("SELECT `id` FROM `prod_group` WHERE `name`='"+ group +"'"); sample = Global.sqlQueryResult("SELECT `product`.`id`, `product`.`name`, `prod_unit`.`short_name`, `product`.`comments` " + "FROM `product` LEFT JOIN `prod_unit` ON `product`.`unit`=`prod_unit`.`id`" + " WHERE `product`.`group`='"+ buf[0][0] +"'"); } @Override public Class getColumnClass(int colInd) { return String.class; } @Override public int getColumnCount() { return 4; } @Override public String getColumnName(int colInd) { String colName =""; switch(colInd){ case 0: colName = "Код"; break; case 1: colName = "Наименование"; break; case 2: colName = "Ед. изм."; break; case 3: colName = "Комментарий"; break; } return colName; } @Override public int getRowCount() { return sample.length; } @Override public Object getValueAt(int rowInd, int colInd) { return sample[rowInd][colInd]; } @Override public void addTableModelListener(TableModelListener arg0) {} @Override public boolean isCellEditable(int arg0, int arg1) {return false;} @Override public void removeTableModelListener(TableModelListener arg0) {} @Override public void setValueAt(Object arg0, int arg1, int arg2) {} } }


Ответ

Анонимные классы удобны там, где цель существования типа - применение в одной единственной точке на всё приложение. Внутренний (нестатический) класс существует внутри внешнего и может быть там скрыт. Кроме того сам имеет доступ к скрытому состоянию родителя.
Если такие "суперспособности" не принесут ощутимой пользы, то стоит склоняться к отдельным классам.
Отдельные классы читаются лучше (и соответствуют Single responsibility) при прочих равных.
А вообще, это достаточно тонкая грань между хорошим кодом и плохим. Чувство прекрасного развивается при чтении чужого кода, где ты распутывая клубок алгоритма подмечаешь для себя какие-то элегантные решения и злишься на излишнюю запутанность других.

Алгоритм определения коллизии цилиндра и сложного тела

Дано:
1) Сложное тело (меш ландшафта), состоящее из треугольных полигонов
2) Простое тело (к примеру цилиндр). Для него известна точка центра и все его измерения.
Нужен алгоритм определения наличия пересечения этих двух тел. При этом, сложное тело много больше простого (по размерам и количеству вершин).
Основная задача - как можно быстрее ответить, есть ли пересечение между этими телами. Допускается предобработка сложного тела.
Какие вообще есть подходы для решения подобной задачи?

Так же скажу сразу, что нужен именно алгоритм, а не какой-то физический движок, который все это сам определит.


Ответ

Разбить поиск на этапы. Первый это грубое отсечение, по крайним координатам тел. Если коллизия не найдена, значит тела не пересекаются. Если найдена, тогда преступаем к детальному отсечению по полигонам попавшим в эту область.
Можете почитать более детально про алгоритмы Sweep And Prune и V-Clip

Проблема с настройкой меню bootstrap'а

Здравствуйте. Подскажите пожалуйста такую вещь. Я создал меню через bootstrap, прописал стили. Но когда я начал уменьшать размер меню, то он стал "съедать буквы". Нужно как-то поднять их. Спасибо.
.navbar-collapse { background: linear-gradient(to top, #4c4e5a 0%, #2c2d33 100%); border-radius: 5px; } .navbar-nav>li>a { color: white; } .navbar-nav>li>a:hover { color: #FF6600; height: 36px } .navbar-nav>li { border-right: 1px solid gray; height: 100%; } .nav { height:30px; font-size: 18px; } Zont-SPB

E-mail:

Телефон:



Ответ

Высота навбара в бутстрапе влияет не только на .navbar { height: xxx; }, но и на свойства других компонентов, например отступов у ссылок .navbar .nav > li > a { padding: xxx; }
Исходники бутстрапа написаны в LESS (SASS в четвертой версии), оба препроцессора позволяют использовать переменные для кастомизации стилей. На высоту навбара влияет переменная $navbar-height
Так как вы не используете LESS/SASS-версию бутстрапа, возможности повлиять на высоту навбара у вас две:
Перейти на http://getbootstrap.com/customize/, поменять значение @navbar-height и собрать себе уникальный css-файл, и подключить уже его, вместо https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css Открыть исходники бутсрапа и найти все места, где фигурирует переменная $navbar-height, пересчитать значения свойств во всех этих местах и разместить стили у себя, они применятся поверх стандартных бутстраповских

среда, 30 января 2019 г.

Button перехода на сайт

Нужно чтобы при нажатии на кнопку программа переводила на сайт компании.


Ответ

Добавьте в обработчик кнопки:
Uri address = Uri.parse("ссылка на сайт компании"); Intent intent = new Intent(Intent.ACTION_VIEW, address); startActivity(intent);

Процесс не может получить доступ к файлу (Исключение HRESULT: 0x80070020)

При попытке запустить сайт в IIS появляется окно с ошибкой:
Процесс не может получить доступ к файлу, так как этот файл занят другим процессом. (Исключение из HRESULT: 0x80070020)

Сайт развернут на 80 порту. Ранее такой ошибки не наблюдал. Около недели назад появлялась эта ошибка, но перезапуск Visual Studio решил проблему и больше ошибка не появлялась. Сейчас ошибка появилась вновь, но ни перезапуск Visual Studio, ни перезагрузка компьютера не решили проблему. Кто сталкивался с данной проблемой, подскажите, как решить? Нашел пару статей по похожим ошибкам, но везде не то.

Нашел вот эту статью: Ошибка 0x80070020 при использовании сайта Центра обновления Windows или Центра обновления Майкрософт для установки обновлений
Обновил систему, перезагрузил компьютер, очистил мусор, скопившийся в системе, перезагрузил компьютер - не решило проблемы. Да, понимаю, что ошибка в IIS, но на всякий случай проверил. Антивируса у меня на компьютере нет.


Ответ

Решение проблемы оказалось следующим:
Запустить командную строку и написать в ней команду:
netstat -aon | find ":80"
в результате, в окне командной строки будет видно следующее:

Необходимо найти процесс, который прослушивает необходимый нас порт. Здесь мы видим, что процесс 3544 прослушивает наш занятый 80 порт.
Открываем диспетчер задач и ищем там наш процесс по идентификатору(ИД):

Как видим - это программа Skype. Открываем Skype, и выполняем следующие действия:
Инструменты -> Настройки... -> Дополнительно -> Соединение
В появившемся окне будет несколько настроек, нас интересует «Для дополнительных входящих соединений следует использовать порты 80 и 443», поэтому убираем активную галочку:
Для дополнительных входящих соединений следует использовать порты 80 и 443
Сохраняем изменения. Перезапускаем Skype, заходим в Диспетчер служб IIS и запускаем сайт, который во время попытки запуска валился с ошибкой.
Подсказка для решения была найдена на MSDN: Ошибка 0x80070020 при запуске веб-сайта в IIS 7.0

Многопоточность, блокировка доступа

Есть приведенный ниже код, суть в том, что функции Add(), Read(), Modify(), Remove(), вызываются извне и в хаотичном порядке, с разным периодом во времени.
Уже сломал голову, подскажите с помощью какой технологии языка C# мне организовать одновременный доступ к разным элементам массива MyList? И чтобы во время удаления/добавления новых элементов, текущие процессы не сбивались с толку, например в потоке ReadThread в данную секунду обрабатывается 5ый элемент массива и в туже секунду потоком RemoveThread уничтожается 4ый, индекс 5ого измениться, как быть?
Делал объект Lock для каждой структуры свой и блокировал отдельные элементы MyList, но тоже не решило проблемы добавления, удаления.
class test { //переменные List MyList = new List(); //блокировка доступа Object Lock = new Object();
//буфер и поток для обработки событий Add BlockingCollection AddBuffer = new BlockingCollection(); Thread AddThread;
//буфер и поток для обработки событий Read BlockingCollection ReadBuffer = new BlockingCollection(); Thread ReadThread;
//буфер и поток для обработки событий Modify BlockingCollection ModifyBuffer = new BlockingCollection(); Thread ModifyThread;
//буфер и поток для обработки событий Remove BlockingCollection RemoveBuffer = new BlockingCollection(); Thread RemoveThread;
//конструктор public test() { if(!AddThread.IsAlive) { AddThread = new Thread(new ThreadStart(AddBufferReader)); AddThread.IsBackground = true; AddThread.Start(); }
if(!ReadThread.IsAlive) { ReadThread = new Thread(new ThreadStart(ReadBufferReader)); ReadThread.IsBackground = true; ReadThread.Start(); }
if(!ModifyThread.IsAlive) { ModifyThread = new Thread(new ThreadStart(ModifyBufferReader)); ModifyThread.IsBackground = true; ModifyThread.Start(); }
if(!RemoveThread.IsAlive) { RemoveThread = new Thread(new ThreadStart(RemoveBufferReader)); RemoveThread.IsBackground = true; RemoveThread.Start(); } }
//Добавляем internal void Add(string Name, string InputString) { //добавляем имя структуры которую надо добавить AddBuffer.Add(new MyStruct(Name, InputString)); } void AddBufferReader() { foreach(var MyStruct in AddBuffer.GetConsumingEnumerable()) { lock(Lock) { //некоторые условия, не все будет добавлено в MyList if(true) { //add, add MyList.Add(new MyStruct(MyStruct.Name, MyStruct.MyString)); } } } }
//Читаем internal void Read(string Name) { //добавляем имя структуры которую надо прочитать и вывести/обработать ReadBuffer.Add(Name); } void ReadBufferReader() { foreach(var Name in ReadBuffer.GetConsumingEnumerable()) { lock(Lock) { for(int i = 0; i < MyList.Count; i++) { if(MyList[i].Name == Name) { //долгие вычисления break; } } } } }
//Изменяем internal void Modify(string Name, string NewString) { //добавляем имя структуры которую надо прочитать и вывести/обработать ModifyBuffer.Add(new MyStruct(Name, NewString)); } void ModifyBufferReader() { foreach(var MyStruct in ModifyBuffer.GetConsumingEnumerable()) { lock(Lock) { for(int i = 0; i < MyList.Count; i++) { if(MyList[i].Name == MyStruct.Name) { //долгие вычисления MyList[i] = new MyStruct(MyList[i].Name, MyStruct.MyString); break; } } } } }
//Удаляем internal void Remove(string Name) { //добавляем имя структуры которую надо удалить из MyList RemoveBuffer.Add(Name); } void RemoveBufferReader() { foreach(var Name in RemoveBuffer.GetConsumingEnumerable()) { lock(Lock) { for(int i = 0; i < MyList.Count; i++) { if(MyList[i].Name == Name) { //remove, remove MyList.RemoveAt(i); break; } } } } }
struct MyStruct { internal string Name; internal string MyString;
public MyStruct(string Name, string MyString) { this.Name = Name; this.MyString = MyString; } } }


Ответ

Я бы начал с ReaderWriterLockSlim или ReaderWriterLock
В этой документации приведён полноценный пример использования. Краткая суть в том, что читать могут сразу несколько потоков. Писать может только один. Читающий поток может захотеть писать и тогда он запрашивает блокировку на запись , что предотвращает появление новых читателей, пока объект не освободится и не завершится запись. Читатели, на время, пока объект заблокирован и происходит запись, ждут. Максимальное время ожидания регулируется вами.
Для реализации более гранулированной блокировки вы можете объявить "корзины" для элементов, которые находятся в процессе чтения и "корзину" для элементов, находящихся в процессе правки, то есть использовать не один а два или более экземпляров ReaderWriterLockSlim. Однако, будьте осторожны. Грануляция блокировок всегда черевата мёртвыми блокировками (deadlock).
Представьте, что в вашем MyList два объекта и вы решили блокировать их отдельно. К вам одновременно приходят два запроса. Один - на чтение, другой на запись.
Первый поток забрал первый элемент MyList на чтение. Второй поток забрать второй элемент MyList на запись. Первый поток начал ждать освобождения второго элемента. Он хочет его почитать. Второй поток начал ждать окончания чтения первого элемента. Он хочет его исправить.
Вы в ж... я хотел сказать в deadlock-е. Именно по этому так полезно указывать конечное значение timeout при обращении к ReaderWriterLockSlim
Ну или сразу согласиться, что экземпляр ReaderWriterLockSlim будет один и на запись будет блокироваться весь ресурс целиком. Тогда deadlock-и вам не страшны.

sql запрос средняя сумма

Помогите пожалуйста написать sql запрос вывести по каждому работнику среднею сумму по всем заказам. Пример:
Первая табличка ID_работника Фамилия 1 Иванов 2 Петров 3 Соколов 4 Сидоров
Вторая табличка номер заказа ID_работника date_time Сумма 1 2 2016-09-13 17:06:43.617 10 2 2 2016-09-13 17:06:43.617 20 3 4 2016-09-13 17:06:43.617 25


Ответ

SELECT t1.ID_работника ,AVG(t2.Сумма) FROM [Первая табличка] AS t1 INNER JOIN [Вторая табличка] AS t2 ON t1.ID_работника = t2.ID_работника GROUP BY t1.ID_работника
P.S. кириллица ЗЛО!!! Учите английский.

Как делать SVG резиновым?

Как делать SVG структуру резиновой ?К примеру на такое конструкции
* { margin: 0; } svg { display: table; margin: auto; }
Примерно что бы эта фигура тянулась..
Вырезать из фотошопа или сохранять как изображение не вариант


Ответ

Для этого достаточно обозначить координаты и размер холста за счет атрибута viewBox - и можно делать svg резиновым, за счет уже знакомого width: 100%
* { margin: 0; } .svg-responsive { width: 100%; }

undefined behavior или нет?

В одном из тестов в один из проектов от Mail.ru group встретил следующий код на языке С:
int b = 11; int a = ++b / 2 / 2 * 3 / 9 - b++ + 1;
Есть ли в этом выражении UB?
Если я правильно понимаю, то между двумя точками следования будет (++b / 2 / 2 * 3 / 9 - b++ + 1), где переменная b изменяется дважды. А такой случай не предусмотрен стандартом и результат зависит от реализации.


Ответ

Undefined.
В подтверждение этого утверждения могу привести диагностику:
warning: operation on ‘b’ may be undefined [-Wsequence-point]
от gcc (и g++) -Wall

Зачем нужна ViewModel в шаблоне MVVM, С#?

Недавно начал изучать паттерн MVVM и возникла дюжина вопросов. Один из них - зачем нужна ViewModel? (биндинг можно строить и в модели) Приведите, пожалуйста, примеры либо скиньте ссылки на статьи.


Ответ

Формально говоря, ViewModel - это еще один слой абстракции от реализации UI. Далее много букв.
Смысл её примерно в следующем. В стандартной парадигме MVC оставался открытым вопрос - как корректно "кодировать" логику взаимодействия с пользователем в той части, которая связана именно с пользовательскими действиями, а не с какой-то бизнес-логикой. Типичный пример - скрыть/показать группу полей при перещелкивании радио-батона, ну или, например, выполнить валидацию введенных данных при переходе на другую вкладку в рамках одного таб-контроля. Еще одним примером может быть отображение диалогового окна с запросом подтверждения действия при, например, изменении какого-то элемента.
Т.е. это действия, которые, с одной стороны, могут иметь под собой достаточно сложную логику, а с другой - вообще говоря, имеют к "модели" - цементирующей всю систему сущности, "отлитую в металле" и сохраняемую в базе - довольно отдаленное отношение. Да и с точки зрения архитектуры добавлять в модельный класс десяток булевых полей IsCheckboxSelected исключительно для сиюминутных нужд отображения - несколько некошерно.
До относительно недавнего времени мышки плакали, кололись, но продолжали есть кактус: это все размазывалось между контроллером и view, писались дополнительные классы и прослойки с репозиториями и архитектурная "красивость" решения приносилась в жертву функциональным требованиям.
Но технический прогресс, как известно, неумолим, интерфейсы стали становиться все сложнее и сложнее, асинхронность, юзабилити и все такое всякое стали доминировать. А с другой стороны еще и автоматизированное и юнит-тестирование начало триумфальное шествие по планете, и вопрос о том, как тестировать вьюхи, в которых логика взаимодействия пользователя гвоздями прибита к физическому "рендерингу" стал стоять все более и более остро.
Т.е. с одной стороны хочется иметь возможность писать (и изолированно автоматически тестировать, что тоже немаловажно) логику UI, а с другой - в ассертах очень не хочется завязываться на конкретные лейблы, тэги, контролы и т.д. и т.п.
Парадигма MVVM была разработана с целью разрешить это противоречие. В архитектуру был введен дополнительный слой - тот, что отвечает за взаимодействие с пользователем, но при этом он строится таким образом, чтобы, в идеале, было не важно отображается ли он в WPF-приложении под Windows, текстовой консоли а ля DOS или передается стуком тамтамов. Это достигается за счет того, что сами классы MVVM строятся на базе обычных POCO-объектов, логика - это методы этих же объектов, оперирующие данными в полях объектов + обработчики событий (UI все-таки по сути - штука асинхронная). А физическое отображение этих самых объектов на пользовательский интерфейс - это уже биндинги, шаблоны, конвертеры и прочие плюшки конкретной реализации - работают как производные от нашей вью-модели (т.е. привязываются к ней).
Плюсы - такие классы относительно легко (ну или хотя бы просто возможно) тестировать юнит-тестами, в целом архитектура получается более стройной, крупные приложения быстрее разрабатывать и проще поддерживать. Минусы - дополнительный оверхед на вью-модель и потребность в развитых средствах биндинга.
Как то так.

Загрузка очень большого числа строк в БД

Добрый день. Есть потребность вставить очень большое число строк в БД. В связи с этим два вопроса.
Какое количество строк целесообразно вставлять за один запрос? Есть ли для вставки больших массивов данных в БД способ лучше, чем делать большое число INSERT-запросов?


Ответ

я бы в данном случае воспользовался BCP (Bulk Copy Program), который был специально разработан для загрузки большого объема данных в MS SQL Server
Пример:
bcp WorlWideImporters.Warehouse.StockItemTransactions OUT D:\BCP\StockItemTransactions_native.bcp -m 1 -b 10000 -n -e D:\BCP\Error_out.log -o D:\BCP\Output_out.log -S -T
Если вам надо делать это программным путем воспользуйтесь BULK INSERT (Transact-SQL)
Пример:
BULK INSERT AdventureWorks2012.Sales.SalesOrderDetail FROM 'f:\orders\lineitem.tbl' WITH ( FIELDTERMINATOR =' |', ROWTERMINATOR =' |
' );
По ссылкам можно найти больше примеров использования...

Установка Java в флешку

Возможно ли установить Java прямо на флешку чтобы написаны на Java запускались прямо с флешки и не требовали утановки Java в ОС на которой запускается? Если нет то можно ли найти локальный установщик без скачки Java потоком из установщика?


Ответ

JRE не требует установки и размножается методом Copy&Paste. Многие десктопные Java-программы распространяются как Java-программа со своей JRE в комплекте. Например - Maple.
Другое дело, что под каждую платформу нужна своя версия JRE.

Установить обложку для записи в WordPress

Здравствуйте. Каким образом в WordPress можно установить, скажем так, обложку для каждой записи? Чтобы на выводи записи было сначала изображение, а потом текст записи. Буду благодарен за полезную информацию.


Ответ

Для вывода миниатюр в теме оформления WordPress используется специальная функция the_post_thumbnail()

Как MessageBox останавливает выполенение кода?

Как MessageBox останавливает выполенение кода, до тех пор, пока пользователь не нажмёт на кнопку? Что-то типа _getch()?


Ответ

MessageBox — блокирующая функция. Поэтому он не может пользоваться внутри себя циклом сообщений (так как цикл сообщений висит в ожидании окончания работы MessageBox).
Поэтому внутри MessageBox запускается новый, вложенный цикл сообщений, на время работы функции. События от клавиатуры и мыши обрабатываются в этом новом цикле сообщений, так что диалоговое окно не зависает. По окончанию работы новый цикл завершается, и возобновляется обработка старого с той точки, в которой он был заморожен функцией MessageBox

Это, кстати, означает одну не очень приятную особенность: если у вас MessageBox показывается как часть обработки одного из оконных сообщений (возможно, косвенно), то во время его работы то же самое оконное сообщение может прийти ещё раз, и ваш код вызовется рекурсивно. Поэтому необходимо позаботиться, чтобы либо заблокировать такую вложенную обработку, либо оставить структуры данных в нормальном, консистентном состоянии.

Ошибка cannot resolve overloaded

Учусь программировать на c++. Возникла странная ошибка при работе с функциями:
cannot resolve overloaded function 'max' based on conversion to type 'double'
Сам код:
#include using namespace std; void maxi(double max) { int i; i=0; float y[5]={3,-2,0.9,0.5,1}; max = -999999; for(i=0; i<5; ++i) { if(y[i] > max) { max = y[i]; }
} }
int main() { cout <<"max value:"<< maxi(max); return 0; }
При очистке параметра max уже в функции main выдается другая ошибка.


Ответ

В этом предложении
cout <<"max value:"<< maxi(max); ^^^
вы используете имя max, которое вы не определили. С другой стороны, благодаря директиве
using namespace std;
вы вводите имена из пространства std в глобальное пространство имен. Видимо имя max, которое соответствует стандартному адноритму std::max в пространтсве имен std также было включено в глобальное пространство имен, и компилятор думает, что в предложении, показанном выше вы в качестве аргумента используете функцию max
Объявите переменную max в main
Обратите внимание, что в функции maxi значение аргумента не используется. Оно перезаписывается в функции
void maxi(double max) { int i; i=0; float y[5]={3,-2,0.9,0.5,1}; max = -999999; ^^^^^^^^^^^^^^
Так что нет никакого смысла объявлять параметр для функции, если его значение в функции не используется. Вы могли бы объявить локальную переменную в функции, как, например,
void maxi() { int i; i=0; float y[5]={3,-2,0.9,0.5,1}; double max = -999999;
^^^^^^^^^^^^^^^^^^^^^
Кроме того в предложении
cout <<"max value:"<< maxi(max);
вы пытаетесь использовать результат работы функции. Поэтому функция должна иметь возвращаемое значение отличное от void. Ее определение могло бы выглядеть следующим образом
double maxi() { int i; i=0; double y[5]={3,-2,0.9,0.5,1}; ^^^^^^ double max = -999999;
//... return max; }
Также нет никакого смысла объявлять переменную i вне цикла, так как она используется только в цикле.
Имейте в виду, что в C++ уже имеется стандартный алгоритм std::max_element, объявленный в заголовке , который позволяет находить максимальное значение заданной последовательности.

вторник, 29 января 2019 г.

Появление элемента после длительного нажатия на блок

Здравствуйте! Имеется список приложений, на мобильных устройствах предусмотрено появление кнопки при длительном нажатии любого из пунктов списка. До этого с версткой подобных элементов не сталкивался, прошу подсказать как такие вещи реализуются.


Ответ

$(document).ready(function(){ var shows = 0; $('#longClick').mousedown(function(){ shows = setTimeout(function(){ $('#shower').show(); }, 2000); }); $('#longClick').mouseup(function(){ clearTimeout(shows); }); $('*').not($('#shower')).mousedown(function(){ $('#shower').hide(); }); });

Click me 2 second
Click for close
Click for close

Анонимный интерфейс c#

Есть интерфейс
intefrace IMy { void say(String msg); }
Есть класс
class My { IMy iMy; public My() { iMy = (str) = > Console.WriteLine(str); //ошибка iMy.say("Text"); } }
На строке с //ошибка мне пишет
Cannot convert lambda expression to type IMy, because it is not a delegate type
Что мне надо изменить в коде, чтобы я мог инициализировать переменную iMy моим способом?
P.S. сам пишу на java, и там такая конструкция работает. Какая аналогичная конструкция в c#?


Ответ

Судя по примеру использования вместо интерфейса в данном случае можно использовать делегат Action, например так
class My { Action iMy; public My() { iMy = (str) => Console.WriteLine(str); //ок iMy("Text"); } }

Поиск в JSON строке значения

Мне нужно получить значение из динамичного JSON. Он огромен , поэтому приводить его полностью не имеет смысла. Меня интересует значения тиража, как мне туда добраться максимально изящно?
По логике мне надо найти слово Тираж в строке и перейти в соседнюю ячейку и получить значение.


Ответ

Воспользуйтесь готовыми парсерами. Читать JSON поиском или регулярными выражениями - не очень хорошая идея. Например, свойство Value не обязано идти до свойства Name, оно может идти и после него. Смысл JSON при этом не изменится, а отловить все такие случаи при поиске будет тяжело.
Json.NET поддерживает такую вещь, как запросы JSONPath
var json = @"{ ""Editions"": {}, ""ItemType"": 5, ""Capabilities"": { ""Capabilities"": [ { ""Name"": ""Тираж"", ""Value"": ""20000"", ""AdditionalProperties"": {} }, { ""Name"": ""aaaa"", ""Value"": ""bbb"", ""AdditionalProperties"": {} } ] } }";
var obj = JObject.Parse(json); var value = (string)obj.SelectToken("$.Capabilities.Capabilities[?(@.Name == 'Тираж')].Value");
Если JSON действительно огромный и десериализовать целиком его накладно по памяти, то придется воспользоваться JsonTextReader, десереализуя только небольшие части файла (код приблизительный, без проверок):
string value = null; using (var reader = new JsonTextReader(new StringReader(json))) { // читаем json, пока не придем в объект Capabilities while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "Capabilities") { break; } }
reader.Read();
// каждый объект из массива десериализуем в JObject while (reader.Read()) { if (reader.TokenType == JsonToken.StartObject) { var obj = JObject.Load(reader); if ((string)obj["Name"] == "Тираж") { value = (string)obj["Value"]; break; } } } }

Аналог функции Swap

Есть ли в С# аналог функции Delphi Swap() ? Верно ли я понимаю, что функция swap меняет местами 2 байта ?


Ответ

В комментариях подсказали, где подсмотреть готовое решение:
Для данных типа ushort:
private ushort Swap(ushort number) { var hi = (byte)(number >> 8); var lo = (byte)(number & 0xff); return (ushort)((lo << 8) | hi); }
Для данных типа Int:
int SwapInt(int number) { var hi = (byte)(number >> 24); var lo = (byte)(number & 0xff); return ((number & 0xffff00) | (lo << 24) | hi); }

Как узнать является ли тип перечислением?

Можно ли как-нибудь проверить, является ли тип перечислением, т.е. enum или enum class?


Ответ

#include #include
class A {}; enum E {}; enum class Ec : int {};
int main() { std::cout << std::boolalpha; std::cout << std::is_enum::value << '
'; std::cout << std::is_enum::value << '
'; std::cout << std::is_enum::value << '
'; std::cout << std::is_enum::value << '
'; }
Ну, или
std::cout << std::is_enum
() << '
'; std::cout << std::is_enum() << '
'; std::cout << std::is_enum() << '
'; std::cout << std::is_enum() << '
';

Ошибка сборки: Cannot find -lGL

При попытке сборки проекта Qt Widgets выдает вот такую ошибку:
g++ -Wl,-rpath,/home/keyreal/Qt/5.7/gcc_64/lib -o untitled3 main.o mainwindow.o moc_mainwindow.o -L/home/keyreal/Qt/5.7/gcc_64/lib -lQt5Widgets -L/usr/lib64 -lQt5Gui -lQt5Core -lGL -lpthread /usr/bin/ld: cannot find -lGL collect2: error: ld returned 1 exit status make: *** [untitled3] Ошибка 1 22:41:13: Процесс «/usr/bin/make» завершился с кодом 2. Ошибка при сборке/установке проекта untitled3 (комплект: Desktop Qt 5.7.0 GCC 64bit)`
Ошибку выдает только если создается проект Qt Widgets, с консольным приложением вроде всё работает. Проект создается пустой абсолютно, т.е. туда ничего не внесено и никаких дополнительных классов не используется
ОС - Ubuntu 14.04 с XFCE.


Ответ

Установите пакет libgl1-mesa-dev
Добавлено
Разумеется, нет возможности гарантировать, что на неких специфичных убунтах с нестандартным набором установленных пакетов, обозначенный пакет не затребует что-либо удалить. Речь о стандартной поставке Ubuntu с Gnome, начиная с 14.04 и по 16.04 включительно. Подозреваю, что и для более ранних версий, а также для версий с XFCE ситуация не изменится (самолично не проверял, не пользуюсь этим DE).
Предоставляемые пакетом файлы:
/. /usr /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/libGL.so /usr/lib/x86_64-linux-gnu/libglapi.so /usr/lib/x86_64-linux-gnu/mesa /usr/lib/x86_64-linux-gnu/mesa/libGL.so /usr/lib/x86_64-linux-gnu/pkgconfig /usr/lib/x86_64-linux-gnu/pkgconfig/gl.pc /usr/share /usr/share/bug /usr/share/bug/libgl1-mesa-dev /usr/share/bug/libgl1-mesa-dev/control /usr/share/bug/libgl1-mesa-dev/script /usr/share/doc /usr/share/doc/libgl1-mesa-dev /usr/share/doc/libgl1-mesa-dev/changelog.Debian.gz /usr/share/doc/libgl1-mesa-dev/copyright
Как видно, пакет содержит искомую библиотеку: libGL.so
При установке на систему Ubuntu 16.04 Gnome ничего не запрашивает снести.

Зачем нужны переменные таблицы и когда их лучше использовать?

В MS SQL есть переменные таблицы.
В некоторых случаях я замечал, что темповые таблицы работают быстрее, за счет того, что в них используется параллелизм в отличии от переменных.
Единственный минус темповых таблиц, как я думаю - это то, что их нужно проверять и дропать если они есть перед создание.
Так вот, для каких целей они могут понадобится, когда есть темповые таблицы и когда их лучше использовать?


Ответ

Единственный минус темповых таблиц, как я думаю - это то, что их нужно проверять и дропать если они есть перед созданием.
На мой взгляд это проблема только при @@nestlevel равном 0, да и то не всегда (например, если открываем соединение, создаём #-таблицу, что-то делаем и закрываем соединение, то в проверке нет необходимости). Внутри модуля (триггера или процедуры), если нужно создать #table, то можно не проверять и не дропать (это может быть и вредным), даже если на внешнем уровне уже была создана #table с тем же самым именем.
Т.е., например, есть процедура
create procedure SomeProc as begin set nocount on;
create table #table (id int); insert into #table values (1), (2);
select * from #table; end GO
Можно создать #table и вызвать SomeProc
create table #table (value float); insert into #table values (100.0), (200.0); exec SomeProc; -- #table внутри SomeProc - это другая #table select * from #table; drop table #table; GO
при этом #table, созданная снаружи SomeProc, и #table, созданная внутри SomeProc - разные и между собой не интерферируют. Если внутри SomeProc перед create table #table поставить проверку существования #table и drop table #table, то уничтожится таблица, созданная на внешнем уровне, и код, следующий за процедурой, сломается.
Так вот, для каких целей они могут понадобиться, когда есть темповые таблицы
При выборе между @table и #table, как мне кажется, следует исходить из свойств и особенностей этих двух типов таблиц. У @-таблиц по сравнению с #-таблицами довольно много ограничений, много общего, и есть особенности присущие только @-таблицам.
Подробно этот вопрос освещён здесь и здесь. Ниже некоторое обобщение информации по этим двум ссылкам (неполное).

Хранилище: Вопреки расхожему представлению о том, что @-таблицы хранятся в оперативной памяти, а #-таблицы - в tempdb, разницы в этом плане между ними на самом деле нет. И те и другие хранятся в tempdb, и, также, и те и другие одинаково буферизуются.
Область видимости: #-таблицы доступны на том уровне, на котором они создаются и на вложенных (@@nestlevel больше текущего). @-таблицы доступны только в рамках того batch-а или модуля, в котором они объявляются (впрочем, типированные @-таблицы на вложенные уровни можно передавать параметром).
Жизненный цикл: @-таблицы создаются неявно в самом начале того батча, в котором они объявлены, перед выполнением всех остальных команд (а если это модуль, то перед началом выполнения модуля), независимо от того, будет ли достигнута в процессе исполнения соответствующая declare инструкция, или нет. Вот такой код, например, вполне работает:
if 1 != 0 declare @table1 table (id int); else declare @table2 table (name varchar(20));
select * from @table1; select * from @table2; GO
уничтожаются @-таблицы после выхода из соответствующего батча или модуля, в котором они объявлены.
#-таблицы создаются тогда, когда встречается соответствующая create table инструкция; уничтожаются тогда, когда встречается соответствующая drop table инструкция, либо при уменьшении уровня вложенности (выхода из модуля или exec инструкции), или закрытии соединения (если #-таблица была создана на нулевом уровне вложенности).
Использование в функциях и процедурах: #-таблицы нельзя создавать в пользовательских скалярных и multi-line табличных функциях, @-таблицы - можно. Типированные @-таблицы можно передавать в функции и процедуры параметром. #-таблицы нельзя передавать в функции (хотя можно получить к ним доступ косвенно - через синоним). В процедурах #-таблицы, созданные на внешнем уровне - доступны.
Сollation: При создании @-таблиц столбцы строковых типов (если они присутствуют) наследуют collation от текущей БД. При создании #-таблиц столбцы строковых типов наследуют collation от tempdb, либо от текущей БД, если та является автономной (contained).
Индексы/ключи: До SqlServer 2014 на @-таблицах можно было задавать только уникальные ключи
declare @table table ( id int primary key, uid uniqueidentifier unique )
В SqlServer 2014 с добавлением inline-синтаксиса для создания индексов стало возможным добавлять неуникальные индексы
declare @table table ( value varchar(20), index ix_1 (value) )
В SqlServer 2016 стало возможным добавление уникальных и отфильтрованных индексов
declare @table table ( id int, value varchar(20), index ix_1 unique (value), index ix_2 (id) where value is NULL )
Индексы с include, а также специальные виды индексов на @-таблицах на настоящий момент не поддерживаются.
Компиляция запросов: Оптимизатор запросов во многих случаях полагает, что @-таблица содержит одну единственную строку. На @-таблицах не поддерживаются статистики по столбцам.
Транзакции: Изменение содержимого @-таблиц всегда происходит в системной транзакции, поэтому они нечувствительны к rollback
declare @table table (value int); create table #table (value int); begin tran; insert into @table values (1); insert into #table values (2); rollback; select * from @table; select * from #table; drop table #table;
Параллелизм: Запросы, меняющие содержимое @table (insert/update/delete) не могут использовать параллелизм. Запросы читающие из @table (select) могут иметь параллельный план.
Табличные подсказки: На @-таблицах нельзя использовать табличные подсказки (table hints), на #-таблицы такое ограничение не накладывается.
Другое: @-таблицу нельзя создать при помощи select * into @table from .... Для @-таблиц недоступны truncate table, alter table, create index

разобрать изменить и собрать

Месяцев 3 назад собрал приложение.никаких бд и ничего нет .чтото легкое .Проект сам утерян .теперь мне надо както сделать пару изменеий в проекте заменить текст и тд.Не знаю что делать ?можно ли как то декомпилоровать апк изменить данные и обратно компелировать ?
Очень нужна ваша помощ


Ответ

для проведения таких действий вам потребуется:
dex2jar Java Decompiler ApkTool
Далее выполнить по следующим шагам:
Качаем dex2jar и извлекаем в папку, например С:\Decompile . Качаем Java Decompiler (например JD-GUI) и извлекаем файлы для удобства в ту же папку, куда и dex2jar. Качаем apktool и apktool-install-windows-r04-brut1.tar.bz2 и извлекаем файлы уже в системную папку. По умолчанию C:\Windows. (Не забыть скачать второй архив) Берем нужный apk файл и кладем в папку с dex2jar и Java Decompiler Открываем Командную строку (Обработчик команд Windows) в вышеупомянутой папке (В папке по пустому месте при зажатой кнопке Shift нажимаем правую кнопку мыши и выбираем Обработчик команд Windows). Вводим команду dex2jar <ваш apk файл> и если все прошло хорошо, в той же папке появится файл <название вашего файла>.apk.dex2jar.jar Запускаем jd-gui и открываем полученный на предыдущем шаге файл. (На Windows 7 открывать с правами администратора и с совместимостью Windows XP SP3) Выбираем пункт меню File-Save All Sources и сохраняем. Извлекаем полученный zip архив. Помещаем полученную папку в папку src (надо предварительно создать).(Что бы получилась примерно такая структура С:\Decompile\<название вашего файла>\src\com\android) Опять же в командной строке вводим команду apktool d <название вашего файла>.apk <название вашего файла>, где <название вашего файла>.apk-имя пакета, <название вашего файла>-папка для декомпиляции.
Если все хорошо, тогда в указанной папке будут исходники в двух форматах (java и smali), ресурсы и файлы AndroidManifest.xml, apktool.yml
Таким образом будут получены исходники. Правда после декомпиляции в коде есть, можно сказать, ошибки,например вместо true и false стоят 1 и 0 соответственно.

Различие между context и this

В андроиде есть context-ссылка, а на самой джаве есть this-ссылка. Так вот в чем разница контекста от зиса и можноли пример с контекстом а то я запутался в нем. Благодарю.


Ответ

this и Context – это принципиально разные вещи.
this – это ключевое слово языка Java. this – это ссылка на самого себя. Ссылка на объект, для которого был вызван метод.
Context (в android) – это абстрактный класс, предоставляющий методы для доступа к т.н. глобальной информации (к ресурсам, классам, для управления активити, сервисами и так далее).
Непосредственными субклассами классами Context являются классы ContextWrapper и MockContext. В свою очередь, прямыми субклассами класса ContextWrapper, в том числе, являются классы Application и Service, а непрямым – класс Activity
Пример с Context
getActivity().runOnUiThread(new Runnable() { @Override public void run() { // some actions } });
Здесь, для запуска кода в UI-потоке используется объект класса Activity (который является (непрямым) наследником класса Context).
Еще один пример с Context
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
Здесь в конструктор класса LinearLayoutManager передается объект класса Activity. Такой вызов, возможен, например, из фрагмента.
Из самой активити можно напрямую вызвать:
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
так как this в методах активити является как раз объектом класса Activity

C# - Создание WPF окна в dll

Можно ли создать dll с функцией (в каком-то классе), которая строит WPF окно.


Ответ

Конечно!
Вы точно так же можете из любой функции создать окно:
var window = new MyWindow(); window.Show();
Не забудьте подключить сборки PresesntationCore, PresentationFramework и WindowsBase, а в свежей версии ещё и System.Xaml. И вы можете точно так же определить класс с окном в DLL, как и в основном приложении, через XAML.
Если у вас не получается добавить XAML для окна, вам понадобится вручную отредактировать csproj, как указано здесь

Если вы не в UI-потоке, и у вас WPF-приложение, вам придётся перебросить выполнение туда. Например, так:
Application.Current.Dispatcher.InvokeAsync(() => { var window = new MyWindow(); window.Show(); });

Если у вас консольное приложение, всё немного сложнее, т. к. у вас нету UI-потока. Вам нужно его создать. Как это делать, написано здесь
Вот рабочий пример:
var thread = new Thread(() => { var window = new MyWindow(); window.Show(); Dispatcher.Run(); });
thread.SetApartmentState(ApartmentState.STA); thread.Start();

Возможно ли средствами javascript прочитать сокеты по ip/порту стороннего сервера?

Сейчас с помощью php получаю данные из разных сокетов по ip:port (с помощью фунуции fsockopen). Это делается для получения играющей в данный момент композиции на разных радиостанциях:
$open = fsockopen($radioip,$radioport,$errno,$errstr,'.5'); if ($open) { fputs($open,"GET /7.html HTTP/1.1
User-Agent:Mozilla

"); stream_set_timeout($open,'1'); $read = fread($open,255); }
В результате основной javascript на главной странице регулярно обращается к этому php на сервере. Хочется, чтобы всё это работало без лишних запросов к серверу, а средствами самого браузера. Возможно ли сделать подобную функцию на javascript - чтобы передавать ей ip и port а в результате получать необходимые данные?


Ответ

К сожалению, любые запросы браузером вне вашего "Origin" возможны только, если на той отвечающей стороне в заголовках ответов есть Access-Control-Allow-Origin с вашим origin. Это дело все закрыто для безопастности, т.к. если бы можно было с любого сайта вызывать AJAXом другой - очень много всего плохого можно было бы делать так.
Подробнее про кросс-доменный AJAX например вот тут
Websockets при этом вам в данном случае совершенно не помогут, т.к. это отдельный протокол обмена данными между сервером и клиентом. И причем последнее время браузеры все чаще форсируют wss (шифрованные вебсокеты), для которых помимо поддержки Websockets еще и SSL на этом поддерживающем сервере нужен. Так что вам особо без промежуточного php скрипта не обойтись.
Если вы задаетесь этим вопросом по причине большой нагрузки на ваш сервер - стоит задуматься облегчением этого всего дела чем-то типа тех же websockets. Только не сторонними серверами, а вашим собственным. Который будет например сам с какой-то определенной частотой обновлять свой кэш по удаленным серверам и с определенной частотой(или по факту изменения) присылать информацию клиентам. В websockets соединение держится и в нем возможен двухсторонний диалог между клиентом и сервером. Тем самым клиентам не нужно будет постоянно обращаться к какой-либо страничке, а они просто получат websocket message по факту его отправки. Такое можно реализовать например на Node.js или ASP.net. На PHP лично я не видел подобных штук.

Прямоугольник с закругленными углами (xml, shape)

Можно ли программно сделать прямоугольник, у которого закруглить все углы кроме одного? Знаю, как сделать прямоугольник со всеми закругленными углами, но можно ли как-то сделать что бы один угол был не закругленным?
Для всех закругленных углов использую:


А нужно прямоугольник, который бы выглядел вот так:


Ответ


Как спроектировать проект? DTO, Anemic, MVVM

Что имеем:
Проект представляет из себя WPF приложение, взаимодействующее с сайтом, локальной БД и отображающее данные в пользовательском интерфейсе.
Пример работы:
На сайте есть что-то вроде топиков, которые время от времени обновляются. Нужно "скачивать" последнее состояние этих топиков и писать в локальную базу, назовем это синхронизацией. После синхронизации мы можем осуществлять быстрый поиск по базе, делать различные пометки, добавлять в избранное и т.д., взаимодействуя через интерфейс пользователя.
Видение структуры:
Модель получается одна, что для базы, что для MVVM. Однако еще я хочу создать также слой API, который будет взаимодействовать с сайтом и возвращать экземпляры моделей. Но тогда и в API понадобится модель.
В итоге получается 2 слоя (или 3?) - API и БД (+ MVVM). Работают с одной моделью. Значит нужно использовать Anemic модель? Или лучше разделить модели, для каждого слоя сделать свою?
Теперь про логику взаимодействия с VM. Если пользователь захочет получить топики по критериям, VM должен запустить синхронизатор, дождаться завершения и только после этого делать запросы к базе. Правильно ли будет синхронизаторы (парсеры), которые через API будут получать топики и обновлять их в базе, выделить в отдельные классы или предоставить эту логику VM-мам?

Что получилось:
Слой API, взаимодействующий с сайтом Слой БД Синхронизаторы, связывающие API и БД VM-ы, взаимодействующие с БД и API через синхронизаторы Общая DTO Anemic модель для API, БД и MVVM.

Правильно ли использовать данные разделения и подход к проектированию в целом?


Ответ

Жуткий поток сознания, который сложно понять.
У вас по сути десктопное приложение клиент к какому то сайту, которое позволяет забирать данные с сайта, просматривать их оффлайн и добавлять какую-то мета-информацию. А значит вот вам мои фломастеры...
Я предпочитаю подход, где есть модели(сущности) и сервисы, которые что-то могут сделать с этими сущностями, то есть anemic.
Модели (сущности) Не стоит плодить dto без надобности. А значит модель(сущность) "топик" будет одной для бд и для клиента сайта и для вьюмоделей, пока не потребуется иначе.
Слой доступа к данным - от него зависит всё. Я предпочитаю рассматривать его как внешнее хранилище. А это значит, что есть подобие Repository/Storage, из которого можно достать данные или положить. Он должен принимать сущности на своем внешнем уровне и внутри себя хранить как ему вздумается. Например быть разделенным на 2 слоя - верхний слой работает с сущностями, а нижний с простыми типами.
Тут много вариантов реализаций и от него зависит будут ли модели anemic. Я не приветствую rich model, которая знает как себя хранить, но модель, вырожденная в dto - тоже плохо, поэтому у меня модели содержат и данные и некоторые методы, которые мешают сохраняться напрямую и инода вынуждают использовать dto (но на практике у меня от dto больше проблем, чем от чистого anemic)
Клиент к сайту - модуль-обертка. В простом случае это 1-2 класса, которые прячут внутри себя сетевые запросы и трансляцию данных их в сущности. Вводить собственные типы данных на границе модуля (и возможно писать дополнительный адаптер/маппинг) есть смысл только если этот модуль будет переиспользоваться в других проектах или очень хочется большей изоляции модулей или у нас ORM, который сильно мешает. Иначе нарушаем YAGNI
Вид (WPF+MVVM) - WPF отображает, а MVVM предоставляет данные для отображения и связывает вид с моделью. MVVM дает данные для отображения и бегает в модель за данными или с просьбой выполнить какую то работу, но сам не содержит логику приложения. Его дело связать вид и логику приложения. Хотя даже при этом вьюмодели получаются жирными, поэтому некоторые добавляют контроллеры (MVVMC) к вьюмоделям, которые и берут на себя общение с моделью.
Синхронизация - это сервис, который относится к модели (не путать с сущностями), а не к виду, поэтому существует не как часть вьюмоделей.
Так мы получили условно модули. Работает все это вместе так:
Пользователь нажимает кнопку "синхронизировать" WPF кнопка забиндена на команду вьюмодели и срабатывает эта команда вьюмодель прямо или косвенно обращается к сервису синхронизации и просит "синхронизируй". Сама вьюмодель ничего большего не делает Сервис синхронизации используя клиент к сайту получает данные в виде сущностей и передает их слою базы данных для хранения. вьюмодель или ждет окончания синхронизации или использует события. вьюмодель отображает данные (лезет за ними в бд например) Те же сущности используются для отображения, ну разве что оборачиваются вьюмоделями(хорошая привычка).
Остались еще дополнительные данные, которых нет на сайте - пометки, метка "избранное" и так далее. Их можно хранить отдельно от сущности "топик", а можно как часть этой сущности (клиент к сайту просто не затронет те поля, что не знает). Декомпозиция слишком спорный процесс - я вот не люблю много колонок в бд, но сохранение и вычитывание графа тоже писать лениво.
Введение DTO - только при необходимости. DTO или сущности конкретного модуля (или использование простых типов) позволяют добиться большей изоляции модуля...но YAGNI требует подумать "а оно нам надо?"
Старайтесь обозначить границы модулей, чтобы работать только с ними. При этом внутренности модуля скрыты. Даже если нужна какая то внутренняя часть, то постарайтесь обеспечить доступ через фасад (границу модуля)

Использование async/await в Python

Почитал про использование async/await в других языках программирования и не совсем понял, как и когда их используют. Для чего они вообще нужны? С помощью них можно улучшить уже существующий код? В каких случаях не стоит их использовать?
PEP 492 introduced support for native coroutines and async / await syntax to Python 3.5. A notable limitation of the Python 3.5 implementation is that it was not possible to use await and yield in the same function body. In Python 3.6 this restriction has been lifted, making it possible to define asynchronous generators:
async def ticker(delay, to): """Yield numbers from 0 to *to* every *delay* seconds.""" for i in range(to): yield i await asyncio.sleep(delay)
PEP 530 adds support for using async for in list, set, dict comprehensions and generator expressions:
result = [i async for i in aiter() if i % 2]
Additionally, await expressions are supported in all kinds of comprehensions:
result = [await fun() for fun in funcs if await condition()]


Ответ

Смотрите. Async/await нужен для того, чтобы не блокировать поток выполнения на время ожидания какого-нибудь асинхронного события. Конструкция Async/await превращает по сути процедуру в корутину (сопрограмму): она прекращает своё выполнение на время await, дожидается асинхронного события, и возобновляет работу.
В не-async-варианте ожидание получается блокирующим, или нужно вручную делать трюки: запускать операцию и подписываться на её окончание. Async делает код более простым, линейным.
Пример (на псевдокоде):
Async:
DownloadToFile(url): filename = GetFilename() content = await DownloadUrl(url) WriteToFile(filename, content) ReportSuccess()
Не-async:
DownloadToFile(url): filename = GetFilename() BeginDownloadUrl(url, onfinished: lambda content: StoreContent(content, filename))
StoreContent(content, filename) WriteToFile(filename, content) ReportSuccess()
Вы видите, что без async контекст выполнения (локальные переменные и т. п.) приходится передавать в «хвост» функции (continuation) вручную. Если async-вызовов много, аналогичный код без async быстро становится сложным.

Важное отличие async- от синхронной функции — async-функция возвращается к вызывающему коду в момент первого выполнения await (если тот ещё не завершён). Вызывающий код может дождаться полного окончания работы при помощи await, а может и продолжить работу самостоятельно.

Использование async/await имеет смысл там, где у вас есть ожидание, не связанное с нагрузкой на процессор. Например, ожидание прихода данных из интернета, или чтения файла с диска. В этом случае вы освобождаете поток физический выполнения для системы, но логическое выполнение продолжается (после возврата из await).