• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Формы и потоки

  • Автор темы Guest
  • Дата начала
G

Guest

Хотел бы узнать по двум вопросам:

1. Как форме удаётся висеть, не пожирая ресурсов, и при этом не спать? То есть реагировать на все нажатия, перетаскивания и т.д..

2. Как можно в своём классе (не имеющего никакого отношения к System.Windows.Forms.Control) создать методы, аналогичный Control.Invoke и Control.BeginInvoke, которые гарантированно выполнялись бы в потоке объекта, даже если бы вызывались из других потоков?
 
M

mr_ST

1) Она таки жрет ресурсы, но очень мало. Почитайте что такое очередь сообщений в win и как она работает.
2) В общем случае никак.
 
L

LuMee

2. Как можно в своём классе (не имеющего никакого отношения к System.Windows.Forms.Control) создать методы, аналогичный Control.Invoke и Control.BeginInvoke, которые гарантированно выполнялись бы в потоке объекта, даже если бы вызывались из других потоков?
Для начала неплохо бы определиться, что такое "поток объекта".
 
Y

YAK

<!--QuoteBegin-Незнайка1965+-->
<span class="vbquote">(Незнайка1965)</span><!--QuoteEBegin-->которые гарантированно выполнялись бы в потоке объекта, даже если бы вызывались из других потоков?[/quote]А мне казалось, что в .Net все действия с объектами выполняются в потоке, в котором они были созданы... (кроме value-types, конечно)
 
L

LuMee

А мне казалось, что в .Net все действия с объектами выполняются в потоке, в котором они были созданы... (кроме value-types, конечно)
Почему так? Один объект вполне может использоваться несколькими потоками. Собственно, поэтому и существуют все эти хитромудрые механизмы синхронизации (мониторы, мьютексы и прочие другие).
 
G

Guest

А мне казалось, что в .Net все действия с объектами выполняются в потоке, в котором они были созданы... (кроме value-types, конечно)
Не-а. Открытый метод какого-либо объекта в общем случае выполняется в том потоке, откуда его вызвали.
Собственно, для этого и нужны методы Conrtol.BeginInvoke, Control.Invoke.
 
L

LuMee

Можно попробовать такой финт ушами.
Завести некий класс-синглтон, инстанс которого будет содержать очередь делегатов и "вечный" поток, который будет доставать делегаты из очереди и вызывать на подконтрольных объектах.
Далее делаем некий базовый класс, в котором будет метод Invoke. Этот метод будет просто принимать делегат и класть его (и, м.б., какие-то дополнительные параметры) в вышеописанную очередь.
Далее все классы, которым нужен этот Invoke, наследуем от этого базового класса.
Таким образом, все действия, выполняемые через Invoke, будут всегда выполняться в одном и том же потоке. Можно также реализовать InvokeRequired: проверять, что текущий поток является тем самым "вечным" потоком синглтона.
 
Y

YAK

да, ошибся.
А мне казалось, что в .Net все успешные действия с объектами (i.e. Control) могут выполнится только в потоке, в котором они были созданы... (кроме value-types, конечно)
Может вот такой вариант? сделать extention методы Get и Set для класса Control, которому будет передаватся свойство и значение и выполнятся в своем потоке. Что-то наподобие того, как сделано в WPF ?
 
G

Guest

очередь делегатов и "вечный" поток, который будет доставать делегаты из очереди и вызывать на подконтрольных объектах.
Вечный поток делается с помощью бесконечного цикла с засыпанием (например, Thread.Sleep(100);), или есть другие средства?

И ещё, у меня была мысль из одной формы вызывать другую в отдельном потоке, но как только выполнялся конструктор этой самой другой формы, поток сразу заканчивался. Получалась парадоксальная ситуация: форма есть, а потока для неё - нет. Соответственно, когда во второй форме вызывался метод this.Invoke, выбрасывалось NullReferenceException.
Более-менее приемлемый выход такой:

secondForm=new SecondForm(...); // В самой форме будет this.Show();
while(!secondForm.IsDisposed)
{
Thread.Sleep(100);
}

, но предпочёл запускать вторую форму в отдельном процессе (думаю перевести на AppDomain).
 
L

LuMee

Вечный поток делается с помощью бесконечного цикла с засыпанием (например, Thread.Sleep(100):), или есть другие средства?
Да, думаю, такой подход подойдет. Получается такое тело цикла:
- читаем очередь делегатов и выполняем, пока не опустеет;
- как только очередь опустела, засыпаем на некоторое время.


Что касается форм, то создавать форму в отдельном потоке - неудачная затея, на мой взгляд. Лучше, чтобы весь UI был в одном потоке, а в другие потоки выностить уже какую-то рабочую логику (по мере выполнения которой можно обнолять UI).
 
G

Guest

Да, думаю, такой подход подойдет. Получается такое тело цикла:
- читаем очередь делегатов и выполняем, пока не опустеет;
- как только очередь опустела, засыпаем на некоторое время.
Хорошо, а как сделать так, чтобы BeginInvoke выполнялся именно в этом потоке?
 
L

LuMee

Хорошо, а как сделать так, чтобы BeginInvoke выполнялся именно в этом потоке?
Не совсем понял вопрос. BeginInvoke сам по себе будет выполнен в том потоке, в котором будет вызван, однако его действия сведутся к добавлению делегата в вышеупомянутую очередь. Сам же делегат будет выполнен в специальном "делегатном" потоке, который обслуживает эту самую очередь.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!