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

Тема в разделе ".NET", создана пользователем -, 29 янв 2010.

  1. Гость

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

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

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

    mr_ST Гость

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

    LuMee Well-Known Member

    Регистрация:
    2 май 2006
    Сообщения:
    477
    Симпатии:
    0
    Для начала неплохо бы определиться, что такое "поток объекта".
     
  4. YAK

    YAK Гость

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

    LuMee Well-Known Member

    Регистрация:
    2 май 2006
    Сообщения:
    477
    Симпатии:
    0
    Почему так? Один объект вполне может использоваться несколькими потоками. Собственно, поэтому и существуют все эти хитромудрые механизмы синхронизации (мониторы, мьютексы и прочие другие).
     
  6. Гость

    Не-а. Открытый метод какого-либо объекта в общем случае выполняется в том потоке, откуда его вызвали.
    Собственно, для этого и нужны методы Conrtol.BeginInvoke, Control.Invoke.
     
  7. LuMee

    LuMee Well-Known Member

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

    YAK Гость

    да, ошибся.
    Может вот такой вариант? сделать extention методы Get и Set для класса Control, которому будет передаватся свойство и значение и выполнятся в своем потоке. Что-то наподобие того, как сделано в WPF ?
     
  9. Гость

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

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

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

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

    LuMee Well-Known Member

    Регистрация:
    2 май 2006
    Сообщения:
    477
    Симпатии:
    0
    Да, думаю, такой подход подойдет. Получается такое тело цикла:
    - читаем очередь делегатов и выполняем, пока не опустеет;
    - как только очередь опустела, засыпаем на некоторое время.


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

    Хорошо, а как сделать так, чтобы BeginInvoke выполнялся именно в этом потоке?
     
  12. LuMee

    LuMee Well-Known Member

    Регистрация:
    2 май 2006
    Сообщения:
    477
    Симпатии:
    0
    Не совсем понял вопрос. BeginInvoke сам по себе будет выполнен в том потоке, в котором будет вызван, однако его действия сведутся к добавлению делегата в вышеупомянутую очередь. Сам же делегат будет выполнен в специальном "делегатном" потоке, который обслуживает эту самую очередь.
     
Загрузка...

Поделиться этой страницей