Отправляет email-рассылки с помощью сервиса Sendsay

[prg] Равзвести цикл на потоки

Привет уважаемому собранию.

C#, VS2017.

Есть большая текстовая база. Ищу в ней циклом:

string line;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains(textBox1.Text) == true)
listBox1.Items.Add(line);
}

Как видно из нагрузки на процессор, поиск идёт на единственном ядре.
Можно как-то распределить эту задачу равномерно по всем ядрам/потокам?
Ядер у меня 6, потоков 12.

Ответить   Fri, 28 Dec 2018 07:15:19 +0300 (#3598716)

 

Ответы:

Vande omentaina, Кирилл!

Я бы на вашем месте использовал Parallel.ForEach в сочетании с
ReadLines.
Дока с похожим примером:
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-write-a-simple-parallel-foreach-loop

В вашем случае лямбдочка должна выглядеть как-то так:
// WARNING! Untested code, use only for reference!
Parallel.ForEach(reader, (line => {
if (line.Contains(textBox1.Text))
listBox1.Items.Add(line);
}
});

Ответить   Fri, 28 Dec 2018 12:12:21 +0200 (#3598760)

 

Я бы на вашем месте использовал Parallel.ForEach в сочетании с
ReadLines.

Здравствуйте.
Совсем плохая идея. Как то давно попадалась статейка, что обращение к диску
параллелить даже вредно. Представьте, что несколько потоков начнут ломиться
к диску? Диск физически не сможет читать одновременно данные из разных мест
файла. Все равно все встанут в очередь или еще хуже начнут дергать головки
пытаясь получить свой кусок из-за этого общее время только увеличится.
Операция то простецкая, ну в смысле арифметики, которой совсем нет в данном
коде, идет поиск совпадений в строке. Поэтому и ядер лишних и потоков тут не
надо. Тупо все упирается в скорость чтения с диска. Если очень хочется , то
я бы обеспечил непрерывное чтение с диска в массив скажем строк по 1000, и
уже этот массив можно отдавать на параллельную обработку. Прочитали первые
1000, отдали. Следующие продолжают считываться, а прочитанные пошли на
сравнение. Да и вообще как видно по textBox при работе предложенного кода
топикстартера вся форма должна вешаться на время прохода по файлу если он
конечно уже не организовал отдельный поток.
Удачи!

Ответить   Sat, 29 Dec 2018 05:13:46 +1000 (#3598886)

 

здравствуйте.

возникла задача увеличения длины запроса в apache. а именно запроса get.

каким образом это сделать. перерыл почти все но ничего так и не нашел.
делаю
LimitRequestLine 32768
в виртуал хосте но ничего не меняется.

если у кого нибудь есть опыт с этим, поделитесь пожалуйста.

спасибо.

Ответить   Thu, 10 Jan 2019 14:14:42 +0400 (#3600140)

 

Mai omentaina, gozaltech!

Так он же by design ограниченной длины. То есть по спецификации восемь
килобайт - и усё.
Пруфлинк (см. первый же ответ):
https://stackoverflow.com/questions/2659952/maximum-length-of-http-get-request

Ответить   Thu, 10 Jan 2019 20:56:31 +0200 (#3600214)

 

Привет

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

в любом случае, вопрос снят установкой директивы
LimitRequestLine в apache.conf

спасибо

Ответить   Fri, 11 Jan 2019 09:18:24 +0400 (#3600257)

 

здравствуйте.

нужно получать и отслеживать изменение текста строки состояния сторонней
программы.

программа не сложная, написана с использованием чистого winAPI.

дескриптор окна статусбара известен.

пытался получить текст средствами SB_GETTETX/SBGETTEXTLENGTH - количество
символов получаю, но когда пишу в буффер, ничего не пишется.

и вопрос, как отслеживать изменение текста?

спасибо

Ответить   Fri, 18 Jan 2019 12:43:45 +0400 (#3601263)

 

Приветствую всех!
Если целевое окно принадлежит другому процессу, то буфер, который вы
выделяете в своем процессе ему недоступн, поскольку каждый процесс имеет
свое изолированное виртуальное адресное пространство.
Чтобы получить требуемый текст, вы должны создать буфер в чужом процессе,
получить в этот буфер строку текста и прочитать ее в своем процессе (все это
делается средствами Win aAPI).
См. по теме
OpenProcess
ReadProcessMemory
WriteProcessMemory
VirtualAllocEx

Разумеется, оба процесса должны принадлежать одному пользователю, либо ваш
процесс должен иметь права на чтение и запись в другие процессы (например,
иметь администраторские права).

Как варианты для отслеживания: либо перехват оконных сообщений, либо MSAA.

Успехов. анатолий.
Исходное сообщение > нужно получать и отслеживать изменение текста строки состояния сторонней

Ответить   "i_chay" Fri, 18 Jan 2019 21:08:32 +0300 (#3601325)

 

здравствуйте.

по поводу получения текста, правильно ли я понял суть?

я выделил память в процессе, и текст действительно получается.

но правильно ли я все делаю?

вот кусок кода, который за это отвечает

[DllImport("user32.dll")]
static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr
childAfter, string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, int Msg, int wParam,
IntPtr lParam);

[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int
lParam);

[DllImport("user32.dll")]
static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out int
lpwdProcessID);

[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(uint dwDesiredAccess, bool
bInheritHandle, int dwProcessId);

[DllImport("kernel32.dll")]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr
lpAddress, int dwSize, uint flAllocationType, uint flProtect);

[DllImport("kernel32.dll")]
static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
int dwSize, uint dwFreeType);

[DllImport("kernel32.dll")]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr
lpBaseAddress, byte[] lpBuffer, int dwSize, IntPtr lpNumberOfBytesRead);

[DllImport("kernel32.dll")]
static extern bool CloseHandle(IntPtr hObject);

const int WM_USER = 0x0400;
const int SB_GETTEXT = (WM_USER + 2);
const int SB_GETTEXTLENGTH = (WM_USER + 3);
const uint PROCESS_ALL_ACCESS = (uint)(0x000F0000L | 0x00100000L |
0xFFF);
const uint MEM_COMMIT = 0x1000;
const uint MEM_RELEASE = 0x8000;
const uint PAGE_READWRITE = 0x04;

IntPtr statusHwnd = FindWindowEx(windowHwnd, IntPtr.Zero,
"msctls_statusbar32", null);
GetWindowThreadProcessId(windowHwnd, out int pid);
IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
int length = SendMessage(statusHwnd, SB_GETTEXTLENGTH, 0, 0);
IntPtr remoteBuffer = VirtualAllocEx(hProcess, IntPtr.Zero,
length + 1, MEM_COMMIT, PAGE_READWRITE);
SendMessage(statusHwnd, SB_GETTEXT, 0, remoteBuffer);
byte[] localTextBuffer = new byte[length + 1];
ReadProcessMemory(hProcess, remoteBuffer, localTextBuffer,
length + 1, IntPtr.Zero);
VirtualFreeEx(hProcess, remoteBuffer, 0, MEM_RELEASE);
CloseHandle(hProcess);
string text = Encoding.ASCII.GetString(localTextBuffer);
MessageBox.Show(text);

поповоду отслеживания текста я пока не совсем понял, буду смотреть.

Ответить   Sat, 19 Jan 2019 10:25:19 +0400 (#3601370)

 

здравствуйте

получилось получить текст из строки состояния и отслеживать изменени путем
использования win events.

получилось что-то типа приведенного ниже.

если есть идеи или замечания что можно поправить, буду рад знать.

получить текст

private static string getStatusbarText()
{
IntPtr statusHwnd = FindWindowEx(windowHwnd, IntPtr.Zero,
"msctls_statusbar32", null);
GetWindowThreadProcessId(windowHwnd, out int pid);
IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
int length = SendMessage(statusHwnd, SB_GETTEXTLENGTH, 0, 0);
IntPtr remoteBuffer = VirtualAllocEx(hProcess, IntPtr.Zero,
length + 1, MEM_COMMIT, PAGE_READWRITE);
SendMessage(statusHwnd, SB_GETTEXT, 0, remoteBuffer);
byte[] localTextBuffer = new byte[length];
ReadProcessMemory(hProcess, remoteBuffer, localTextBuffer,
length + 1, IntPtr.Zero);
VirtualFreeEx(hProcess, remoteBuffer, 0, MEM_RELEASE);
CloseHandle(hProcess);
string text = Encoding.Default.GetString(localTextBuffer);
return text;
}

отслеживание текста

private static IntPtr hhook;
delegate void WinEventDelegate(IntPtr hWinEventHook, uint
eventType,IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint
dwmsEventTime);
static WinEventDelegate procDelegate = new
WinEventDelegate(WinEventProc);

GetWindowThreadProcessId(windowHwnd, out int pid);
IntPtr statusHwnd = FindWindowEx(windowHwnd, IntPtr.Zero,
"msctls_statusbar32", null);
hhook = SetWinEventHook(EVENT_OBJECT_NAMECHANGE,
EVENT_OBJECT_NAMECHANGE, statusHwnd, procDelegate, pid, 0,
WINEVENT_OUTOFCONTEXT);

static void WinEventProc(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint
dwmsEventTime)
{
if (getStatusbarText() == "some text")
{
// Do some work
}
}

Ответить   Sun, 20 Jan 2019 16:26:38 +0400 (#3601522)