Многопоточность и события

Zhmot
Дата: 27.05.2006 21:22:57
У меня есть несколько COM-объектов. Мне нужно написать обработчики событий для этих объектов. Но вызов событий происходит очень часто: несколько раз в секунду.
В обработчике этий событий я создаю новые потоки и обрабатываю уже в новых функциях.
Но производительность естественно за счет этих потоков не намного увеличивается!!!! Все тормозит, т.к. уходит время на создание потока и передачу управления в функцию.

Вопрос: возможно ли как-то запихать сам обработчик события в дополнительный поток, чтобы не создавать каждый раз новый поток ?

Надеюсь, понятно, что я имел ввиду )
saint
Дата: 27.05.2006 23:21:38
а Вам действительно требуется создавать новый поток?
Тут есть два варианта:
1) делать без доп потоков.
2) использовать пул потоков.

но вообще, если у вас большие требования к производительности, пишите native-код.
Zhmot
Дата: 30.05.2006 12:22:48
автор
а Вам действительно требуется создавать новый поток?

Наверное, нужен, т.к. в обработчике нужно обработать код, довольно немаленький.
Существует ли метод, позволяющие как-то "перенаправлять" обработку события в дополнительный поток автоматически, не создавая каждый раз в обработчике события новый поток с передачей в другую функцию????
Т.е. проблема в том, что для программы критично время на создание потока (т.к. события инициируются очень часто, 2-3 раза в секунду и их несколько).
maXmo
Дата: 30.05.2006 12:27:56
нужно само сообщение посылать в нужный поток.
------------------
- А как в Интеpнете pаботать? - Сначала нужно узнать, что вам нужно rtfm
Лиман Артём
Дата: 30.05.2006 12:36:00
может можна организовать асинхронную обработку очереди? Есть поток (один), котрый вермя от времени сканирует некую очередь (Queue). Обработчик события ничего не делает тяжелого, просто регистрирует в этой очереди данные, которые необходимо обработать. Сканирующий поток колбасит эти данные по мере их поступления в очередь.
_______________________________________________________
Never ask users what they want, or they'll tell you.
Картинка с другого сайта.
Alexey Kudinov
Дата: 30.05.2006 12:37:51
Zhmot
события в дополнительный поток автоматически, не создавая каждый раз в обработчике события новый поток с передачей в другую функцию????Т.е. проблема в том, что для программы критично время на создание потока (т.к. события инициируются очень часто, 2-3 раза в секунду и их несколько).
Я не очень понял - вы не хотите создавать потоки в обработчиках ? ну так создайте их заранее и подпишитесь в них на ваши события - это раз.
Помните, что события содержат в себе коллекцию своих обработчиков (GetInvocationList) и их можно вызывать асинхронно. Это два
Вот кусок кода, из живого проекта (VS 2003) ServerMessageSent - событие
		void IServerCommunicator.SendMessageToClient(IServerMessage p_oMessage)
		{
			if(ServerMessageSent!=null)
			{
				AsyncCallback myAsyncCallback = new AsyncCallback(CallbackMethod);
				foreach(ServerMessagesHandler handler in ServerMessageSent.GetInvocationList())
				{
					handler.BeginInvoke(p_oMessage, myAsyncCallback, handler);
				}
			}
		}

		private void CallbackMethod(IAsyncResult ar)
		{
			ServerMessagesHandler del = (ServerMessagesHandler)ar.AsyncState;
			try
			{
				del.EndInvoke(ar);
			}
			catch(SocketException)
			{
				//Убираем "мертвого" клиента от подписчика на наши сообщения и
				//сообщаем об этом всем остальным
				ServerMessageSent -= del; 
				throw new Exception("Произошло аварийное отключение от системы нотификации одного из подключенных SpiderManager-ов");
			}
		}
Zhmot
Дата: 30.05.2006 13:37:23
Спасибо, Alexey.
Но я в этом деле новичок, и не смог применить, то что Вы написали.
Помогите пожалуйста применительно к моему коду.
COM сервер TEClientLib.
Два объекта, два события.
Как использовать GetInvocationList и это реализовать???


using TEClientLib;

public partial class Form1 : Form
    {
        SlotTable tabFut1;
        SlotTable tabFut2;  

public Form1()
{

        tabFut1 = new TEClientLib.SlotTable();
        tabFut1.ReplEnd += new _ISlotTableEvents_ReplEndEventHandler        (tabFut1_ReplEnd);

        tabFut2 = new TEClientLib.SlotTable();
        tabFut2.ReplEnd += new _ISlotTableEvents_ReplEndEventHandler(tabFut2_ReplEnd);

        void tabFut1_ReplEnd(int OpenID)
        {
            Thread1 = new Thread(new ThreadStart(AnimateSeries1));
            Thread1.Start();
        }
        
        void tabFut2_ReplEnd(int OpenID)
        {
            Thread2 = new Thread(new ThreadStart(AnimateSeries2));
            Thread2.Start();
        }

}

}

Большое спасибо.
Alexey Kudinov
Дата: 30.05.2006 13:54:13
Хм, для того чтобы применить мой способ, надо изменить этот TEClientLib. Т.к. асинхронный вызов реализуется в самом поставщике события.

Кстати помните, что WinForms - они не thread safe, т.е. если чего-то хотите асинхронно нарисовать на форме, то надо использовать метод класса Form BeginInvoke
 void tabFut2_ReplEnd(int OpenID)
        {
            this.BeginInvoke (AnimateSeries2);
        }
примерно так
maXmo
Дата: 30.05.2006 14:07:35
так сделано просто для удобства. На евент вешается пучок делегатов и в обработчике они по очереди вызываются. Можно просто нафигарить делегатов (если их нужно несколько) и по очереди вызывать.
------------------
- А как в Интеpнете pаботать? - Сначала нужно узнать, что вам нужно rtfm