Страницы

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

пятница, 7 декабря 2018 г.

Можете объяснить суть invoke

Есть основной поток, в котором я создаю все Controls в winforms. И есть второй поток, который вызывается через срабатывание события. В результате этого события мне нужно изменить значение DataSource у DataGridView. В результате возникает ошибка, что доступ к контролу пытается получить не основной поток, в котором был создан контрол. Решением является использование методов Invoke\BeginInvoke. Но саму суть я не понимаю этих методов и как их реализовать в коде. В создаваемом втором потоке используется функция доступа к dgv
private void RefreshTables() { try { if(con.State == ConnectionState.Closed) { con.Open(); } sql = "select rowid, * from OpenPos"; adapOpenPos = new SQLiteDataAdapter(sql, con); dsOpenPos = new DataSet(); adapOpenPos.Fill(dsOpenPos); dataGridView1.DataSource = dsOpenPos.Tables[0]; dataGridView1.Columns[0].Visible = false; dataGridView1.Columns[15].Visible = false; dataGridView1.Update(); con.Close();
if (con.State == ConnectionState.Closed) { con.Open(); } sql = "select rowid, * from ClosePos"; adapClosePos = new SQLiteDataAdapter(sql, con); dsClosePos = new DataSet(); adapClosePos.Fill(dsClosePos); dataGridView2.DataSource = dsClosePos.Tables[0]; dataGridView2.Columns[0].Visible = false; dataGridView2.Columns[14].Visible = false; dataGridView2.Update(); con.Close(); } catch (Exception e) { MessageBox.Show(e.Message); } }


Ответ

Суть метода Invoke довольно проста - он принимает делегат и выполняет его в том потоке, в котором был создан элемент управления, у которого вызывается Invoke. Как вы могли заметить, если обращаться к контролам в WinForms не из того потока, в котором они были созданы, будет выброшено исключение. Соответственно, метод Invoke полезен в случаях, когда необходимо работать с контролом из других потоков. Метод BeginInvoke делает то же самое, но асинхронно.
Небольшой пример использования Invoke
private void ButtonInvoke_Click(object sender, EventArgs e) { var myThread = new Thread(ThreadFunction); myThread.Start(); //метод выполняется в другом потоке }
private void ThreadFunction() { Thread.Sleep(1000); Action action = () => listBox1.Items.Add("value"); // Свойство InvokeRequired указывает, нeжно ли обращаться к контролу с помощью Invoke if (InvokeRequired) Invoke(action); else action(); }
Стоит также отметить, что async/await, добавленные в C# 5, позволяют обойтись без Invoke
private async void ButtonAsync_Click(object sender, EventArgs e) { listBox1.Items.Add("first"); await Task.Run(async () => { await Task.Delay(1000); }); // этот код будет продолжен в UI потоке, // и здесь нет необходимости использовать Invoke listBox1.Items.Add("second"); }

Как можно оценить суровость выполненного запроса?

Например, есть некоторый сервис, который время от времени выполняет запросы и нужно определить насколько запрос был "тяжелым".
По каким критериям это можно оценить?
Первое, что пришло на ум- это замерить загрузку процессора на SQL Server до и во время выполнения запроса.
По каким критериям еще можно понять, что запрос оказался тяжелым и мог негавтивно сказаться на работу других пользователей с БД?
Собственно, это нужно для программы балансировки нагрузки, что бы выполнять тяжелые запросы в наиболее подходящее время. Собственно, не помешал бы минимальный пример, как эту статистику можно получить из когда программы.


Ответ

Тяжесть зависит от плана выполнения. План выполнения может меняться в зависимости от статистики по таблицам. Статистика может устаревать и порождать неверные планы. Так что "тяжесть" - величина непостоянная.
Кроме того, в SQL Server есть кэш данных, и запрос, выбирающий данные их кэша, ес-но будет выдавать меньше физических чтений с диска. Поэтому при замерах стоит смотреть на количество логических чтений, а не только на количество физических.
Грубо можно оценить, замерив время и IO напрямую:
SET STATISTICS TIME ON SET STATISTICS IO ON
запрос
Выполнить несколько раз, отбросить максимальное и минимальное значение по CPU, по остальным - взять среднее.
Показатели IO будут зависеть от плана, так что они при последовательных выполнениях не поменяются. Для воспроизведения промаха кэша - почистите его вызовом CHECKPOINT; DBCC DROPCLEANBUFFERS;
Из .NET значения статистики можно получить, выставлением свойства sqlConnection.StatisticsEnabled = true + вызовом sqlConnection.RetrieveStatistics()

Что делать с "плохим" запросом - достаточно обширный вопрос. Минимальный набор действий
пересчитать статистику для используемых таблиц(обязательно, иначе есть шанс бороть несуществующую проблему!) получить свежий план выполнения если план плохой - оптимизировать запрос, индексы или структуру базы
Что точно не стоит делать - это править SQL наугад. Оптимизация SQL - достаточно простой процесс, но при этом нужно точно представлять механизм выполнения запросов SQL Server, иначе можно получить кучу скрытых проблем :)

Что такое стек и куча? [дубликат]

На данный вопрос уже ответили: Представление кучи и стека 3 ответа Я изучаю C# и пытаюсь понять что такое стек и куча. В большинстве примеров, стек подается как массив у которого есть функции push() и pop(). Но это не достаточное объяснение для меня. Вот к примеру, у нас есть функция Calculate()
void Calculate() { int x; int y; object z; }
Какую роль в этом примере играет стек, а какую роль играет куча?


Ответ

Если рассматривать язык c# сам по себе, в отрыве от реализации, то действительно знать о том, что такое "стек" вам нет необходимости.
Но если вы хотите хорошо понимать тот инструмент, которым пользуетесь, то можно посмотреть немного под капот.
Платформа Microsoft .NET использует стековый байт-код Intermediate Language (IL, CIL, MSIL).
То есть код, который вы напишите, будет записан в опкодах этого языка и уже непосредственно его и будет выполнять CRL.
Посмотрим на какой-либо простой код c# и на то, как он записан опкодами:
void Main() { int a = 15; int b = 10; int c = a - b; Console.WriteLine(c); }
IL-код я получил в программе Linqpad, в IL DASM будет такой же:
IL_0000: nop IL_0001: ldc.i4.s 0F IL_0003: stloc.0 // a IL_0004: ldc.i4.s 0A IL_0006: stloc.1 // b IL_0007: ldloc.0 // a IL_0008: ldloc.1 // b IL_0009: sub IL_000A: stloc.2 // c IL_000B: ldloc.2 // c IL_000C: call System.Console.WriteLine IL_0011: nop IL_0012: ret
Что мы видим при наведении мыши на ldc или stloc? Мы видим всплывающие подсказки "pushes int value onto stack" или "pops value from top of stack".

То есть все ваши инструкции на c# оказываются очень тесно связанными со стеком. Даже простые операции типа сложения чисел проходят через стек. И циклы фактически тоже разворачиваются в стековые инструкции.
Это как раз устройство нижележащего этажа для c#. Современные языки программирования достаточно часто используют концепцию стековых машин, c# -- один из них.
PS Если хочется погрузиться в эту тему более основательно, то хорошей отправной точкой может стать статья Введение в MSIL [Кенни Керр, пер. Aquila]

Разбиение числа на цифры независимо от длины

Изучаю java и для практики решаю простенькие логические задачки, типа нахождения счастливого билетика. Часто встречаются задания, где на входе есть n-значное число, и необходимо что-то сделать с цифрами, из которого оно состоит (дан диапазон чисел от 1 до 999, найти, в скольких числах из диапазона встречается цифра 2). Все, что я знаю и умею - это разбивать ни цифры делением:
int a = 123 / 100 = 1 int b = 123 / 10 % 10 = 2 int c = 123 % 100
Остальная часть задачи проверяется условием. Собственно сам вопрос: есть ли в java какой либо метод, позволяющий разбивать число на цифры и не привязываться к его длине? Например, числа, в которых необходимо искать 2 и ммм 13! вводятся с клавиатуры? И длина числа ограничена только типом int.


Ответ

Что-то вы сильно мучаетесь с делением. Берите с конца. Взятие остатка от деления "%" числа на 10, всегда вам даст последнее из его цифр. И в цикл! int a = Integer.MAX_VALUE; StringBuilder s = new StringBuilder(); System.out.println(a); while(a>0) { s.insert(0, a%10); a = a / 10; } System.out.println(s.toString()); Причем навскидку, написать данный алгоритм можно не одним способом, выбирайте, кому как нравится: StringBuilder s = new StringBuilder(); for(int a=Integer.MAX_VALUE; a>0; a/=10) s.insert(0, a%10); System.out.println(s); Так же вам, и только вам, решать записывать цифры подряд, а в конце переворачивать строку, либо сразу писать все в начало строки.

Как будет hash (хеш) по-русски?

Для написания дипломных работ требуют использования только русских слов, а не заимствованных из английского языка. Например нельзя использовать: брандмауэр, логин, браузер. На английском можно только название программ, ОС и т.д. Друзья, есть ли у Вас идеи, как называют хеш (в моем случае хеш пароля) в научной литературе на русском? Я встречал - "дайджест сообщения", но "дайджест" тоже английское слово "digest". Видел перевод "сводка сообщения" в википедии, но никаких материалов, где такое словосочетание используется нет.


Ответ

В ГОСТ Р 34.11-94, начиная прямо с названия, используется слово «хэш» и его производные («хэширование»). Так что с этим словом все в порядке. За исключением вопроса правописания («хэш» или «хеш»). В ГОСТах тут слегка разброд и шатания, два ГОСТа одного года (34.10-94 и 34.11-94; да, первый неактуален, см. далее) использовали разные варианты («хеш» и «хэш» соотв.), в ГОСТ 34.10-2001 уже «хэш.» Так что, скорее всего, через «э», но тут я не уверен. Это, лучше, спросите на gramota.ru :)

Округление до N знаков после запятой в с++

есть число типа double, например 4.64452675
Как в С++ сделать округление до N знаков после запятой? Либо отсечение? Не нашел нужной функции


Ответ

static const double powerOfTen[] = { 1.0, 10.0, 100.0, ... };
double truncated = std::trunc(d * powerOfTen[N]) / powerOfTen[N]; double rounded = std::floor(d * powerOfTen[N] + 0.5) / powerOfTen[N];

Оператор delete: удаление массива

Здравствуйте. :) Вот такой вопрос возник, почему вот этот после выполнения int *x = new int[2]; delete x; идентичен вот этому int *x = new int[2]; delete []x; Везде где читал, сказано что массив нужно удалять вторым способом.


Ответ

Если вы выделяли память при помощи new[], вы обязаны освободить её с помощью delete[]. Так гласит стандарт.
Освобождение такой памяти как-то по-другому (delete без [] или вообще free) является Undefined Behaviour. Если в программе есть Undefined Behaviour, она имеет право вести себя как угодно: может ничего плохого не делать, может вылететь в любой точке, отформатировать ваш винчестер или выбросить из окна вашего кота.
You have been warned.