Страницы

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

четверг, 12 декабря 2019 г.

Как вызвать асинхронный метод из Main?

#c_sharp #async_await


Работает ли данный код асинхронно? По идее, должен, но у меня почему-то основной
поток блокируется.

static void Main(string[] args)
{
    DoSomething();
    Console.WriteLine("Now u can type something");
    Console.ReadLine();
}        

public static async void DoSomething()
{
    using (FilmContext context = new FilmContext())
    {
        var c = await (from b in context.Films select b).ToListAsync();

        foreach (var a in c)
        {
            Console.WriteLine(a.Descripton);
        }
    }
}

    


Ответы

Ответ 1



Смотрите. Вы хотите, чтобы вывод в функции Main происходил после окончания DoSomething? Значит, вам нужно (асинхронно) дождаться окончания работы этой функции. Для этого нужны следующие изменения: Функция должна возвращать не void (async void вообще нужен лишь в специфических случаях, т. к. его невозможно дождаться через await), а Task. Вы должны в Main дождаться окончания DoSomething, используя await DoSomething();. Чтобы в функции Main можно было использовать await, проще всего сделать её тоже асинхронной. В свежих версиях C# (начиная с C# 7.1) это легко делается при помощи объявления static async Task Main(string[] args). Итого: static async Task Main(string[] args) { await DoSomething(); Console.WriteLine("Now u can type something"); Console.ReadLine(); } public static async Task DoSomething() { using (FilmContext context = new FilmContext()) { var c = await (from b in context.Films select b).ToListAsync(); foreach (var a in c) { Console.WriteLine(a.Descripton); } } } Если вам нужно, чтобы выполнение проходило параллельно, возникает вопрос, насколько дорого конструирование FilmContext:. Если этот код выполняется быстро, то ваш начальный код был верен, но лучше бы переписать его в таком виде: static async Task Main(string[] args) { var t = DoSomething(); Console.WriteLine("Now u can type something"); Console.ReadLine(); if (!t.IsCompleted) Console.WriteLine("Waiting until task finishes..."); await t; } public static async Task DoSomething() { using (FilmContext context = new FilmContext()) { var c = await (from b in context.Films select b).ToListAsync(); foreach (var a in c) { Console.WriteLine(a.Descripton); } } } Если же new FilmContext выполняется медленно, то проще всего выгрузить весь DoSomething() на пул потоков: static async Task Main(string[] args) { var t = Task.Run(DoSomething); Console.WriteLine("Now u can type something"); Console.ReadLine(); if (!t.IsCompleted) Console.WriteLine("Waiting until task finishes..."); await t; }

System.in.read() или всё же Scanner?

#java #scanner


Заметил во многих книгах используется: System.in.read() - это получить что-то с клавиатуры.
Почему там допустим не используется класс Scanner? Потому что System.in.read() это
быстрее, нежели чем создавать экземпляр класса Scanner и далее создавать вот такую
конструкцию:

Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();


или же 

Scanner scanner = new Scanner(System.in);
int x = scanner.nextInt();


Поискал на Stackoverflow и не нашел отличия System.in.read и класса Scanner. 
    


Ответы

Ответ 1



Разница есть, и притом, существенная. System.in.read() может считать только 1 символ в виде char. В то же время, Scanner - это универсальная штука, позволяющая считывать в том формате, что надо. Если требуется считать по символам, то не следует заморачиваться, а использовать System.in.read(). В остальных случаях - это, в частности и файлы, используем Scanner.

Ответ 2



Потому что искусство подачи учебной информации включает умение рассказывать только о том, что относится к теме, без привлечения дополнительных сущностей. Если тема относится к основам считывания данных из потока ввода, то объяснять это через использование токенизатора - это усложнение и отвлечение.

Какие программы и генераторы можно применять для облегчения написания кода svg

#javascript #css #svg #поиск_программ


Какую посоветуете программу для SVG?

Желательно с "генерацией кода" HTML, если есть такое.  

Update

Автор вопроса видимо имел ввиду программы для помощи в написании кода svg
    


Ответы

Ответ 1



Update Посмотрите конец топика. Добавлена утилита, которая сделает из вашего статичного SVG файла анимацию рисования линий с помощью нажатия одной кнопки. Автору, если я правильно понял вопрос нужны инструменты, которые облегчают написание кода SVG. SVG GENERATOR PATH Очень удобная вещь. Перемещаете узловые точки, двигаете рычаги, а внизу пишется код патча. Может быть использован для написания кода для фигурной шапки сайта, для анимашек волн и т.д и т.п Полученный код из генераторов, в период освоения SVG, лучше добавлять инлайн способом, то есть непосредственным копированием в HTML Path Length Calculator Копируете формулу path и получаете его максимальную длину. Вычисление длины path необходима для написания кода анимации рисования линий, посредством изменения атрибута stroke-dasharray SVG Path Builder Добавляете, удаляете, перемещаете узловые точки для получения нужной формы кривой. В нижнем правом углу автоматом пишется код path BOXY SVG Быстрый, многофункциональный векторный редактор Генераторы clipPath https://codepen.io/jh3y/pen/XqVQqa http://bennettfeely.com/clippy/ Генераторы базовых фигур SVG Генератор прямых линий Прямые отрезки – path Генератор прямоугольников Генератор окружностей Генератор эллипсов Генераторы кривых Безье Кубическая кривая Безье – The cubic Bezier curve Кривые Безье второго порядка Гладкая поликривая Безье второго порядка Принцип для всех, вышеперечисленных генераторов svg кода одинаков: двигаете узловые точки, перемещаете их рычаги и копируете код SVG. Процесс использования генераторов нагляден, удобен, сразу видно какие атрибуты path динамически изменяются. Что помогает понять, как они работают. Также их выгодно применять, так как на выходе получается чистый код, без добавления служебной информации, которую вносят векторные редакторы в файл SVG Конвертер SVG path Convert SVG path to all-relative or all-absolute Преобразует все команды либо в относительную, либо в абсолютную форму записи. Инструменты разработки К сожалению ничего, такого, специализированного нет. Да в принципе и не нужно особо. Так как svg легко правится в текстовом редакторе, например: Notepad++ Рисовать сложные фигуры можно в векторных редакторах: Inkscape, Adobe Illustrator. Для рисования простых фигур есть и такие редакторы: editor.method svg-edit.github.io Draw SVG JXNBLK / PATHS Оптимизаторы кода SVG SVGOMG - автор Jake Archibald SVG Editor - автор Peter Collingridge SVGO-GUI - автор GreLI Мне особенно нравится SVG Editor и его в основном использую, практически на каждом приложении. Убирается вся лишняя, служебная информация, можно задать количество знаков после запятой у path. Размер файла svg порою сокращается в несколько раз и код становится читабельным. Update 4.12.2019 Генераторы параметров атрибутов для анимации Cubic-bezier Генератор keysplines Генератор keyTimes Генератор анимации линий Всё просто: перетаскиваете свой файл SVG в окно загрузки утилиты и получаете на выходе готовый файл с анимацией рисования линии.

С# Имя из названия переменной гетера/сеттера

#c_sharp


Есть какие идеи как получить имя в случае, если свойство статическое:

public static class xWrapper
{
    public static Object TestName
    {
        get { return X(nameof(???)); } // вот тут надо получить имя "TestName"
    }
}

    


Ответы

Ответ 1



Решение для .NET 4.5+: public static string GetPropertyName([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "") { return propertyName; } public static Object TestName { get { return X(GetPropertyName()); } }

Ответ 2



1.nameof(PropertyName) 2.Даный код вернет название проперти в геттере и сеттере без прямого указывания названия : MethodBase.GetCurrentMethod().Name.Replace("set_", "").Replace("get_", ""); Код не очень красивый, зато сработает. 3.Третий путь -- подобен второму: вытягивать из стектрейса эту же информацию и подниматся на 1 уровень вверх: public static class Props { public static string CurrPropName => (new StackTrace()).GetFrame(1).GetMethod().Name.Replace("set_", "").Replace("get_", ""); public static string CurrMethodName => (new StackTrace()).GetFrame(1).GetMethod().Name; } И если ты из проперти вызовешь Props.PropName оно вернет тебе название самой проперти. Если вызовешь Props.CurrMethodName -- даст название метода в котором ты сейчас находишся. PS: но мне больше нравится решение MSDN.WhiteKnight

Анимация svg глаз кролика с помощью атрибутов path “d” и “keyTimes”

#css #html5 #svg #анимация #svg_animation


Как можно анимировать svg картинку? Хочу чтобы кролик моргал глазами.



#pa8{
width: 250px;
height:250px;
}
 



    


Ответы

Ответ 1



Взял код из предыдущего ответа, добавил кролику зрачок глаза. переработал анимацию с учетом добавления атрибута keyTimes, которым задаётся неравномерность движения века глаза. Основное условие применения этого атрибута - Количество значений keytimes и values в path должно совпадать. keyTimes="0;0.15;0.18;0.85;1" имеет 5 значений, ровно столько значений должно быть в формуле анимации атрибута d path - 5 подробнее здесь .container { width:90%; height:90%; }


Ответ 2



Если потребуется объяснения каким образом это сделано подробно я объясню Как было сказано на Toster что анимировать img не возможно и это обсуждалось уже милион раз здесь , в вашем случае надо взять весь код из img открыть обычным халявным notepad++ и вынести SVG в html и анемировать тот путь Вот реализация вашей задумки : https://codepen.io/topicstarter/pen/PgLdog я искал в ручную этот path и так как он был ниже того глаза то я просто переместил path c анимацией в самый низ ... И что хочу сказать что toster stackoverflow не база бесплатных исполнений ХОТЕЛОК Конкретно вот этот участок отвечает за эффект : Прошу модераторов простить меня за то что выложил код в песочнице но максимальная длина сообщения 30000 а код составил 35 000

Ответ 3



Пришлось подрихтовать зайца, чтобы он лез в сниппет, я уменьшил точность точек в путях при помощи svg-optimiser и убрал у него несколько областей. Далее открываем отладчик Сhrome и при помощи инспектора выясняем как найти тот путь, который формирует глаза: Как оказалось это второй по счету элемент с классом .a После манипуляций c путем выясняем какие части атрибута пути d формируют внутренние отверстия для левого и правого глаза черном полигоне Разделить путь на внешний контур и внутренние отверстия легко вызвав .split('z') на строке атрибута d Далее добавляем 2 круга, которые будем двигать по кликам мышки и используем 2 пути найденных на предыдущем шаге в качестве clip-path для них let d=document let e=d.querySelectorAll('.a')[1].getAttribute('d').split('z') d.querySelector('svg').innerHTML+=` ` let t,dir=-1,vr=0,vl=0 let xy=(e,x,y) => e.setAttribute('cx', x)||e.setAttribute('cy', y) let tr=(e,x,y) => e.setAttribute('transform', `translate(${x},${y})`) let l=(type,i) => addEventListener(type,()=>dir=i) e=d.querySelectorAll('.a') t=new Date().getTime() l('mousedown',1) l('mouseup',-1) setInterval(()=>{ dir=1 setTimeout(()=>dir=-1,300) },3000) anim() addEventListener('mousemove',ev=>{ let x=ev.clientX/innerWidth-0.5 let y=ev.clientY/innerHeight-0.5 tr(e[2],x*50,y*50) tr(e[3],x*40-10,y*30) }) function anim() { let dt=new Date().getTime()-t vr=Math.min(1,Math.max(vr+dt/88*dir,0)) vl=Math.min(1,Math.max(vl+dt/200*dir,0)) xy(d.querySelector('#left'),345+vl*50,420+vl*125) xy(d.querySelector('#right'),400+vr*50,370+vr*150) t=new Date().getTime() requestAnimationFrame(anim) }

Ответ 4



Это пример анимации кролика но саму картинку я взял из сети :с этого сайта Так же анимировал по технике анимации SMIL Пример рекомендуется к просмотру в полноэкранном режиме

Потеря обработчиков событий после использования LINQ

#c_sharp #события #linq #observablecollection


Есть ObservableCollection mystrings, которой я на старте приложения присваиваю
значения, и делаю обработчик события mystrings.CollectionChanged += mystrings_OnChange;

Однако дальше мне нужно сделать выборку из этой коллекции, отсеить ненужные элементы,
и удалить их из коллекции. Однако когда я делаю 

mystrings = new ObservableCollection(mystrings.Where(x => x ...));


То после этого у меня mystrings новый обьект, который "потерял" обработчики событий.
Как правильнее с этим бороться?
    


Ответы

Ответ 1



Проблема ObservableCollection в том, что она не работает с диапазонами данных одновременно (добавить диапазон, удалить диапазон, заменить диапазон). Предложение добавить диапазоны в API ObservableCollection ещё не реализовано и не будет даже в .NET Core 3.x, так как команда WPF и так очень загружена из-за того, что данное предложение может поломать WPF, который не умеет работать с изменением диапазона данных, а не одного элемента данных. Поэтому вижу три возможности: Пересоздать коллекцию, заново добавить обработчик события CollectionChanged. Вы так и сделали в своём вопросе. Получить коллекцию элементов, которые нужно оставить, очистить ObservableCollection с помощью метода Clear, в цикле добавить в ObservableCollection нужные элементы через Add. Возможно, надо будет отключить обработчик CollectionChanged до Clear и цикла добавления, а затем подключить его заново после цикла. Получить коллекцию элементов для удаления, в цикле удалить из ObservableCollection ненужные элементы через Remove. Возможно, надо будет отключить обработчик CollectionChanged до цикла удаления, а затем подключить его заново после цикла.

Ответ 2



Возможно поможет моя библиотека ObservableComputations. Ваш код с использованием этой библиотеки будет выглядеть так: ObservableCollection filteredMystrings = mystrings.Filtering(x => x ...)); Чтобы этот код работал нужно чтобы mystrings был ObservableCollection.

Ответ 3



скопировать в коллекцию ту выборку которую ты сделал не забудь посмотреть что будет с длинной мой вариант: oc.ClearItems(); foreach(l in enumerable){ oc.InsertItem(l); } специально посмотрел в Microsoft.Docs. оба метода вызывают событие CollectionChanged

Ответ 4



Реализация третьего варианта ответа @Vadim Ovchinnikov, но без создания временной коллекции. //Использованы части кода из ответа @KuzCode public static void Main(string[] args) { var collection = new ObservableCollection(); NotifyCollectionChangedEventHandler handler = (obj, e) => { if (obj is ObservableCollection coll) { Console.Write("items now: "); foreach (var item in coll) Console.Write(item + " "); Console.WriteLine(); } }; collection.CollectionChanged += handler; for (int i = 0; i < 10; i++) collection.Add(i); collection.RemoveNotMatched(t => t >= 5); collection.RemoveNotMatched(t => t >= 7, handler); Console.ReadKey(); } public static void RemoveNotMatched(this ObservableCollection coll , Func predicate) { for (int i = coll.Count()-1; i >= 0; i--) { var item = coll[i]; if (!predicate(item)) coll.Remove(item); } } public static void RemoveNotMatched(this ObservableCollection coll , Func predicate , NotifyCollectionChangedEventHandler handler) { coll.CollectionChanged -= handler; RemoveNotMatched(coll, predicate); coll.CollectionChanged += handler; handler(coll, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } Вывод items now: 0 items now: 0 1 items now: 0 1 2 items now: 0 1 2 3 items now: 0 1 2 3 4 items now: 0 1 2 3 4 5 items now: 0 1 2 3 4 5 6 items now: 0 1 2 3 4 5 6 7 items now: 0 1 2 3 4 5 6 7 8 items now: 0 1 2 3 4 5 6 7 8 9 items now: 0 1 2 3 5 6 7 8 9 items now: 0 1 2 5 6 7 8 9 items now: 0 1 5 6 7 8 9 items now: 0 5 6 7 8 9 items now: 5 6 7 8 9 items now: 7 8 9

Ответ 5



Я предлагаю, возможно, не самый быстрый по производительности способ, но он абсолютно практичен. Просто создайте функцию-расширение для коллекции CopyFrom(), которая принимает List, и добавьте все объекты из списка в вашу коллекцию. Вот пример кода: using System; using System.Collections.ObjectModel; using System.Collections.Generic; using System.Linq; namespace Rextester { public static class Program { public static void Main(string[] args) { var collection = new ObservableCollection(); collection.CollectionChanged += (obj, e) => // добавляем событие { Console.Write("items now: "); foreach (var item in collection) Console.Write(item + " "); Console.WriteLine(); }; for (int i = 0; i < 10; i++) collection.Add(i); // добавляем элементы collection.CopyFrom(collection.Where((item) => item >= 5).ToList()); //делаем выборку } public static void CopyFrom(this ObservableCollection coll, List list) { coll.Clear(); list.ForEach((item) => coll.Add(item)); } } } И пример вывода: items now: 0 items now: 0 1 items now: 0 1 2 items now: 0 1 2 3 items now: 0 1 2 3 4 items now: 0 1 2 3 4 5 items now: 0 1 2 3 4 5 6 items now: 0 1 2 3 4 5 6 7 items now: 0 1 2 3 4 5 6 7 8 items now: 0 1 2 3 4 5 6 7 8 9 items now: items now: 5 items now: 5 6 items now: 5 6 7 items now: 5 6 7 8 items now: 5 6 7 8 9

Canvas кнопка меню

#javascript #svg #анимация #canvas


Всем привет! Подскажите, пожалуйста: какая технология используется для реализации
кнопки меню как на сайте https://www.panoply.co.uk/? Заказчик просит скопировать..
Вижу что canvas, но не могу понять в ручную ли написан код или может фреймворк какой..
Заранее благодарен за любую информацию.
    


Ответы

Ответ 1



Вот собрал вам нечто похожее из подручных средств, в этом примере нет WebGL, все посчитано и нарисовано через 2d контекст. let ctx = canvas.getContext('2d'); let k = 300, a1 = 0, a2 = 0, dir = 0, far = 300, w = canvas.width, h = canvas.height, planes = []; ctx.translate(w/2, h/2); for (var i=-20; i<21; i+=20) { addRect(10,10,20,i,-20) addRect(10,10,-20,i,-20) addDiag(15,10,20,i,-20) addDiag(-15,10,20,i,-20) } addTopDiag(25,15,-25,20) addTopDiag(-25,-15,-25,20) function addTopDiag(x1,x2,dy,dz) { whitePlane([ pt(-x1, dy, -dz), pt(-x2, dy, -dz), pt(x1, dy, dz), pt(x2, dy, dz) ]); } function addDiag(w, h, dx=0, dy=0, dz=0){ whitePlane([ pt(0, h/2+dy, -5), pt(0, -h/2+dy, -5), pt(w, -h/2+dy, dz), pt(w, h/2+dy, dz) ]); } function addRect(w, h, dx=0, dy=0, dz=0){ whitePlane([ pt(-w/2+dx, -h/2+dy, dz), pt(-w/2+dx, h/2+dy, dz), pt(w/2+dx, h/2+dy, dz), pt(w/2+dx, -h/2+dy,dz) ]); } requestAnimationFrame(render) function whitePlane(points){ planes.push({color: 'white', points}); } function pt(x,y,z) { return {x, y, z}; } function project(p) { let sinA1 = Math.sin(a1), cosA1 = Math.cos(a1); let sinA2 = Math.sin(a2), cosA2 = Math.cos(a2); let x = p.x*cosA1 + p.z*sinA1; let z = p.z*cosA1 - p.x*sinA1; let y = p.y*cosA2 + z*sinA2; let kd = k/(z*cosA2 - p.y*sinA2 + far); p.X = kd*x; p.Y = kd*y; } function render() { a2 += dir * 0.1; if (a2 < -Math.PI/2 || a2 > 0) { dir = 0; a2 = a2 > 0 ? 0 : -Math.PI/2; } if (a2 < 0 && a2 > -Math.PI/2) requestAnimationFrame(render); planes.forEach(plane => plane.points.forEach(project)); ctx.clearRect(-w/2, -h/2, w, h); planes.forEach(drawPlane); } function drawPlane(plane) { ctx.fillStyle = plane.color; ctx.beginPath(); ctx.moveTo(plane.points[0].X, plane.points[0].Y); for (var i = 1; i < plane.points.length; i++) ctx.lineTo(plane.points[i].X, plane.points[i].Y); ctx.fill(); ctx.closePath(); } function toggle() { if (a2 < 0 && a2 > -Math.PI/2) return; dir = a2 === 0 ? -1 : 1 requestAnimationFrame(render); } body { background: url(https://picsum.photos/id/22/700/200); } canvas { cursor: pointer; }

Ответ 2



В отличие от соседнего ответа, посчитал почти все точки по формуле и нарисовал при помощи SVG... let cos = Math.cos, sin = Math.sin, k = 1000, a1 = 0, a2 = 0, far = 1000, dir = 0, planes = []; let pts = Array(8).fill(0).map((e, i) => { let a = Math.PI*(.25+.5*Math.floor(i/2)) + (i%2?.2:-.2); return [cos(a)*30, sin(a)*30]; }); let t = -25; whitePlane([pt(0,t),pt(1,t),pt(4,t),pt(5,t)]) whitePlane([pt(2,t),pt(3,t),pt(6,t),pt(7,t)]) for (var i=0; i<3;i++){ let t2 = t+20*i; let t3 = -15+20*i; whitePlane([ pt(4,t2),pt(5,t2),{x:0,y:t2,z:-7},pt(6,t2),pt(7,t2), pt(7,t3),pt(6,t3),{x:0,y:t3,z:-7},pt(5,t3),pt(4,t3), ]) } requestAnimationFrame(render) function whitePlane(points) { let id = "plane_" + planes.length; svg.innerHTML += ``; planes.push({points, id}); } function pt(i, y=0) { return {x:pts[i][0], y, z:pts[i][1]}; } function project(p) { let x = p.x*cos(a1) + p.z*sin(a1); let z = p.z*cos(a1) - p.x*sin(a1); let y = p.y*cos(a2) + z*sin(a2); let d = z*cos(a2) - p.y*sin(a2) + far; return [ (k/d)*x ,(k/d)*y ]; } function render() { a2 += dir * 0.1 if (a2 < -Math.PI/2 || a2 > 0){ dir = 0; a2 = a2 > 0 ? 0 : -Math.PI/2; } dir !== 0 && requestAnimationFrame(render) planes.forEach(plane => window[plane.id] .setAttribute("points", plane.points.map(project))); } function toggle() { if (dir !== 0) return; requestAnimationFrame(render); dir = a2 === 0 ? -1 : 1 } body { background-color: black; overflow: hidden; } svg { width: 200px; height: 200px; cursor: pointer; } polygon { fill: white; }