← 返回

Подключение к Quik и запуск DDE

Пробую подключение к Quik и запуск DDE из примеров (Sample, SampleSMA). Все происходит очень медленно, поискал по форуму, есть несколько сообщений с такими же проблемами. Железо вроде не самое слабое (Phenom II X2 555/8Gb/SSD), система Windows 7 Ultimate 64bit. Запускаются Quik и примеры от имени администратора. Хотелось бы все-таки с помощью Михаила докопаться до возможных причин таких тормозов.

В связи с этим первый вопрос: после установки соединения с Квиком через QuikTrader.Connect() и поступления события Connected секунд где-то через 10 в Квике появляется окно "Выбор активных счетов и задание их очередности", которое висит и пропадает где-то через 30 секунд. Так и должно быть?

Вот код этого консольного приложения:

			Console.WriteLine("Запуск...");

			try
			{
				var waitHandle = new AutoResetEvent(false);

				// создаем шлюз к Quik-у
				var trader = new QuikTrader(@"C:\FinamJunior\info.exe");

				// подписываемся на событие успешного подключения
				// все действия необходимо производить только после подключения
				trader.Connected += () =>
				{
					Console.WriteLine("Подключение было произведено успешно.");

					// извещаем об успешном соединени
					waitHandle.Set();
				};

				Console.WriteLine("Производим подключение...");

				trader.Connect();

				// дожидаемся события об успешном соединении
				waitHandle.WaitOne();
				Console.ReadKey();

				trader.Dispose();
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				Console.ReadKey();
			}

本主题对您有帮助吗?

分享主题

评论 (59)

登录创建账户, 登录或注册以发表评论

Valdis
Valdis

у меня тож примерно так же . секунд 10-30, иногда пошустрей иногда помедленней

Alexander
Alexander

Тоже наблюдаю.

По этому поводу уже была дискуссия - подобное наблюдается только на Windows 7 (как 32bit, так и 64bit) и связано именно со стартом DDE в этой операционной системе (под Windows XP всё моментально).

Если я не ошибаюсь, то: Из окна "Выбор активных счетов и задание их очередности" экспортируются все текущие счета в квике и задаются портфели. Данный экспорт запускается подленным и его медлительность также связаны с особенностью работы Квика в Windows 7.

vvt
vvt 作者

Ну до старта DDE еще не дошло дело. Если я правильно понимаю, то приложение сначала ждет появления окна "Выбор активных счетов и задание их очередности" и после его появления должно программно нажать кнопку "Да". Но почему оно это делает так медленно?

vvt
vvt 作者

Похоже медленное подключение к Квику и запуск ДДЕ происходит из-за множества открытых окон программ (в моем случае Internet Explorer-а с кучей вкладок в каждой), чем их больше, тем медленнее идет процесс. Сейчас запущен только Google Chrome с 30-ю вкладками и сам Квик, соединение и запуск ДДЕ происходит за 16 секунд вместо 4 минут...

dart
dart

vvt: Похоже медленное подключение к Квику и запуск ДДЕ происходит из-за множества открытых окон программ (в моем случае Internet Explorer-а с кучей вкладок в каждой), чем их больше, тем медленнее идет процесс. Сейчас запущен только Google Chrome с 30-ю вкладками и сам Квик, соединение и запуск ДДЕ происходит за 16 секунд вместо 4 минут... Попробуйте на ХР. Выше уже писали что на В7 весь этот процесс занимает больше времени. Моё ИМХО, что это не связано именно с S#. Такое поведение многие отмечали у многих дотнетовских программ при переходе с ХР на В7.

Mikhail Sukhov
Mikhail Sukhov

dart:

vvt: Похоже медленное подключение к Квику и запуск ДДЕ происходит из-за множества открытых окон программ (в моем случае Internet Explorer-а с кучей вкладок в каждой), чем их больше, тем медленнее идет процесс. Сейчас запущен только Google Chrome с 30-ю вкладками и сам Квик, соединение и запуск ДДЕ происходит за 16 секунд вместо 4 минут... Попробуйте на ХР. Выше уже писали что на В7 весь этот процесс занимает больше времени. Моё ИМХО, что это не связано именно с S#. Такое поведение многие отмечали у многих дотнетовских программ при переходе с ХР на В7.

Не смотрел еще причину, но думаю что и да и нет. S# использует поиск окон (что само по себе не быстрый процесс). Возможно в Win7 это работает медленнее, так как безопасность все время расширяется, а ее расширение постепенно подминает и производительность.

На следующей неделе я постараюсь с этим разобраться. Но сразу оговорюсь, ждать чуда не стоит. Если это можно поправить моими силами и в самом S#, я это сделаю. Иначе, увы.

Den
Den

Mikhail Sukhov: Не смотрел еще причину, но думаю что и да и нет. S# использует поиск окон (что само по себе не быстрый процесс). Возможно в Win7 это работает медленнее, так как безопасность все время расширяется, а ее расширение постепенно подминает и производительность.

На следующей неделе я постараюсь с этим разобраться. Но сразу оговорюсь, ждать чуда не стоит. Если это можно поправить моими силами и в самом S#, я это сделаю. Иначе, увы.

Решил написать свои изыскания:

на одном форуме читал про проблему, что GetPixel стал работать в десятки раз медленнее на Win7 по сравнению с Win XP. Человеку надо было читать цвет пикселей игрушки, запущенной в браузере. В итоге он разобрался и написал следущее:

"если получать пиксель используя хэндл рабочего стола (или контекст ус-ва, связанный с раб. столом в случае с GetPixel()), то тупит , если использовать например хэндл браузера, то работает быстро. Вот такая вот магия... "

Михаил, возможно из этого вы по аналогии сможете решить проблему долгого поиска окон на Win7: брать Handle от окна Quik для поиска таблиц.

Артем_2
Артем_2

Очень бесит сидеть на XP только из-за экспорта по DDE 🤨...Михаил можно ли выложить кусок чек кода, который запускает экспорт какой-нить таблицы с при менением поиска окон?- Может совместными усилиями получится нагуглить причину тормозов.

Alexander
Alexander

Артем_2: Очень бесит сидеть на XP только из-за экспорта по DDE 🤨...Михаил можно ли выложить кусок чек кода, который запускает экспорт какой-нить таблицы с при менением поиска окон?- Может совместными усилиями получится нагуглить причину тормозов.

Давно под 7кой пробовали? :) Относительно недавно был фикс, у меня сейчас работает реально шустро.

Артем_2
Артем_2

У меня на рабое семерка(работает в домене), дома виста, и есть комп с XP еще, поэтому есть возможность сравнивать: W7- я плачу Vista - в депрессии XP - Летает

Особенно поражает разница в скорости работы верифаера... В XP он как на межгалактической станции отрабатывает, а в W7 или Vista гораздо медленнее. При разработке, во время тестов - это ОЧЕНЬ ограничивает, поэтому лучше сидеть на XP, т.к. в W7 при такой сорости могут нервы не выдержать. После фикса стал быстрее отрабатывать запуск Quik, но на запуске экспорта я че-то не очень ощутил изменения. Я вот думаю, может это все связано с появлением WPF в новых операционках,который многослоен, может это как-то увеличивает количество окон, участвующих в поиске, надо Spy++ поковырять...

Alexander
Alexander

Артем_2: У меня на рабое семерка(работает в домене), дома виста, и есть комп с XP еще, поэтому есть возможность сравнивать: W7- я плачу Vista - в депрессии XP - Летает

Особенно поражает разница в скорости работы верифаера... В XP он как на межгалактической станции отрабатывает, а в W7 или Vista гораздо медленнее. При разработке, во время тестов - это ОЧЕНЬ ограничивает, поэтому лучше сидеть на XP, т.к. в W7 при такой сорости могут нервы не выдержать. После фикса стал быстрее отрабатывать запуск Quik, но на запуске экспорта я че-то не очень ощутил изменения. Я вот думаю, может это все связано с появлением WPF в новых операционках,который многослоен, может это как-то увеличивает количество окон, участвующих в поиске, надо Spy++ поковырять...

Оставь почту, вечером вышлю файл с экспортом

Артем_2
Артем_2

Спасибо, вот она! nazaroid2@mail.ru

Артем_2
Артем_2

Увы, че-то не получил ничего...

Alexander
Alexander

Артем_2: Увы, че-то не получил ничего...

Вчера очень занят был, сейчас отправил.

Артем_2
Артем_2

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

Den
Den

Артем_2: Понял... Спасибо, все получил! Будем разбираться...

У меня тоже на XP экспорт по DDE летает. На Win7 жутко тормозит - пробовал на 3.2.2, отлаживаться вообще нервов не хватает. Возможно коммент #8 может помочь разобраться...

Артем_2
Артем_2

Есть идеи как сделать оптимизацию, но к сожалению, пока не пробовал их воплотить, т.к. нахожусь в отпуске. Обязательно сообщу че и как, когда поковыряюсь

Артем_2
Артем_2

Если не получится, то по форумам вопросы раскидаю...

Артем_2
Артем_2

Всем доброго дня! Пока что изыскания следующие:

  1. Небольшая статистика запуска 2-х таблиц квика (инструменты и позиции по деривативам) по дде показала, что разница весьма существенная. В моем примере виста отработала в 9 раз медленнее. Статистика условная, т.к. конфигурации компьютеров были разными, хотя и похожими.

Vista

Запуск экспорта по ДДЕ Выпонение метода GetQuikWindows(Process process) заняло 0,3300634 секунд. Метод вернул 12 из 565 окон Выпонение метода GetQuikWindows(Process process) заняло 0,3549551 секунд. Метод вернул 12 из 565 окон Выпонение метода GetQuikWindows(Process process) заняло 0,329384 секунд. Метод вернул 13 из 566 окон Открытие DDE окна => Выпонение метода WaitFor заняло 0,6904268 секунд Остановка DDE вывода => Выпонение метода WaitFor заняло 0,0019952 секунд Запуск DDE вывода => Выпонение метода WaitFor заняло 0,004298 секунд Выпонение метода GetQuikWindows(Process process) заняло 0,355389 секунд. Метод вернул 12 из 566 окон Закрытие DDE окна => Выпонение метода WaitFor заняло 0,355694 секунд Запуск окна с заголовком <инструменты> занял 1,3918877 секунд

       Выпонение метода GetQuikWindows(Process process) заняло 0,3480023 секунд. Метод вернул 12 из 565 окон
       Выпонение метода GetQuikWindows(Process process) заняло 0,3566171 секунд. Метод вернул 12 из 565 окон
       Выпонение метода GetQuikWindows(Process process) заняло 0,3168064 секунд. Метод вернул 13 из 566 окон
       Открытие DDE окна => Выпонение метода WaitFor заняло 0,6788765 секунд
       Остановка DDE вывода => Выпонение метода WaitFor заняло 0,0020404 секунд
       Запуск DDE вывода => Выпонение метода WaitFor заняло 0,0029838 секунд
       Выпонение метода GetQuikWindows(Process process) заняло 0,3298589 секунд. Метод вернул 12 из 566 окон
       Закрытие DDE окна => Выпонение метода WaitFor заняло 0,3300634 секунд
Запуск окна с заголовком <позиции по деривативам> занял 1,3701531 секунд 

Запуск ДДЕ занял: 2,762106 секунд

XP

Запуск экспорта по ДДЕ Выпонение метода GetQuikWindows(Process process) заняло 0,0347218 секунд. Метод вернул 15 из 263 окон Выпонение метода GetQuikWindows(Process process) заняло 0,0358152 секунд. Метод вернул 15 из 263 окон Выпонение метода GetQuikWindows(Process process) заняло 0,0357294 секунд. Метод вернул 16 из 264 окон Открытие DDE окна => Выпонение метода WaitFor заняло 0,0836615 секунд Остановка DDE вывода => Выпонение метода WaitFor заняло 0,0018648 секунд Запуск DDE вывода => Выпонение метода WaitFor заняло 0,0039082 секунд Выпонение метода GetQuikWindows(Process process) заняло 0,0349754 секунд. Метод вернул 15 из 263 окон Закрытие DDE окна => Выпонение метода WaitFor заняло 0,0351794 секунд Запуск окна с заголовком <инструменты> занял 0,1647161 секунд

       Выпонение метода GetQuikWindows(Process process) заняло 0,036516 секунд. Метод вернул 15 из 263 окон
       Выпонение метода GetQuikWindows(Process process) заняло 0,0351818 секунд. Метод вернул 15 из 263 окон
       Выпонение метода GetQuikWindows(Process process) заняло 0,0350804 секунд. Метод вернул 16 из 264 окон
       Открытие DDE окна => Выпонение метода WaitFor заняло 0,0727249 секунд
       Остановка DDE вывода => Выпонение метода WaitFor заняло 0,0012032 секунд
       Запуск DDE вывода => Выпонение метода WaitFor заняло 0,0029322 секунд
       Выпонение метода GetQuikWindows(Process process) заняло 0,0363536 секунд. Метод вернул 15 из 263 окон
       Закрытие DDE окна => Выпонение метода WaitFor заняло 0,0365615 секунд
Запуск окна с заголовком <позиции по деривативам> занял 0,1561724 секунд 

Запуск ДДЕ занял: 0,320936 секунд

  1. Удалось локализовать функцию, которая тормозит. - Это AllToplevelWindows, эта функция вызывается в S# для получения списка окон квика.- AllToplevelWindows в свою очередь вызывает из библиотеки ManagedWinapi.dll функцию FilterToplevelWindows.
  2. В тестах видно, что AllToplevelWindows в висте возвращает гораздо большее количество окон 565 чем в XP 263. Интересно, что удаление значков из трея в висте значительно уменьшило количество окон (565 скатилось до 415) и работа с окнами в моем случае стала работать примерно в 2 раза быстрее. Но если наоткрывать вкладок в браузере, то скорость очень значительно снижается.
  3. Я вывел заголовки окон в висте и XP, в висте оказалось гораздо больше пока непонятных окон без заголовков (330), чем в XP, где такие тоже имеются, но их меньше 152.
  4. Пока это все, что удалось выяснить. Если у кого-то есть идеи и мнения на этом этапе, которые смогут ускорить процесс решения проблемы, пишите, пожалуйста.
Alexander sun
Alexander
Alexander

Артём, спасибо. Посмотрю сегодня чего да как.

Кроме тебя ни у кого нет доступа к этим методам, поэтому названия остальным мало что скажут :)

Alexander
Alexander

AllToplevelWindows - это уже свойство в ManagedApi.dll

dart
dart

Кстати по теме. В W7 х64 ДДЕ достаточно быстро запускается. Почти как в ХР. Версия 2.6.2

Артем_2
Артем_2

Артём, спасибо. Посмотрю сегодня чего да как.

Кроме тебя ни у кого нет доступа к этим методам, поэтому названия остальным мало что скажут :)

Да, у меня тоже собственно не было... Располагал только классом QuikTrminal🤨. Я думал ManagedWinapi.dll заимствованная библиотека:

http://mwinapi.sourceforge.net/doc/html/P_ManagedWinapi_Windows_SystemWindow_AllDescendantWindows.htm

Alexander
Alexander

Артём, спасибо. Посмотрю сегодня чего да как.

Кроме тебя ни у кого нет доступа к этим методам, поэтому названия остальным мало что скажут :)

Да, у меня тоже собственно не было... Располагал только классом QuikTrminal🤨. Я думал ManagedWinapi.dll заимствованная библиотека:

http://mwinapi.sourceforge.net/doc/html/P_ManagedWinapi_Windows_SystemWindow_AllDescendantWindows.htm

Верно, так и есть. Только http://mwinapi.sourceforge.net/doc/html/P_ManagedWinapi_Windows_SystemWindow_AllToplevelWindows.htm - вот как раз AllToplevelWindows. Не совсем понял откуда взялось FilterToplevelWindows в выводах

Артем_2
Артем_2

Дата: меньше минуты назад Артем_2;8981 написал: Цитата: Артём, спасибо. Посмотрю сегодня чего да как.

Кроме тебя ни у кого нет доступа к этим методам, поэтому названия остальным мало что скажут :)

Да, у меня тоже собственно не было... Располагал только классом QuikTrminal. Я думал ManagedWinapi.dll заимствованная библиотека:

http://mwinapi.sourcefor...AllDescendantWindows.htm

Верно, так и есть. Только http://mwinapi.sourcefor..._AllToplevelWindows.htm - вот как раз AllToplevelWindows. Не совсем понял откуда взялось FilterToplevelWindows в выводах

Это я залез через задний так сказать проход внутрь AllToplevelWindows и определил, что


        public static SystemWindow[] AllToplevelWindows
        {
            get
            {
                return SystemWindow.FilterToplevelWindows(new Predicate<SystemWindow>(SystemWindow.ALL.Invoke));
            }
        }

Alexander
Alexander

Есть предложения как от этой функции уйти?

Артем_2
Артем_2

Увы, мои спосбности на этом этапе исчерпали себя😭 Пока никаких предложений нету. Эта функция делает следующее:


public static SystemWindow[] FilterToplevelWindows(Predicate<SystemWindow> predicate)
        {
            List<SystemWindow> wnds = new List<SystemWindow>();
            SystemWindow.EnumWindows((SystemWindow.EnumWindowsProc)((hwnd, lParam) =>
            {
                SystemWindow local_0 = new SystemWindow(hwnd);
                if (predicate(local_0))
                    wnds.Add(local_0);
                return 1;
            }), new IntPtr(0));
            return wnds.ToArray();
        }

Чего с этим делать пока непонятно

Mikhail Sukhov
Mikhail Sukhov

Артем_2: Увы, мои спосбности на этом этапе исчерпали себя😭 Пока никаких предложений нету.

...

Чего с этим делать пока непонятно

Предлагаю задать вопрос на сайте rsdn.ru и уже там дальше провести разбор полетов Это форум для программистов. Боюсь своими силами проблему не решить.

Артем_2
Артем_2

А EnumWindows - это Api


    [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static bool EnumWindows(SystemWindow.EnumWindowsProc lpEnumFunc, IntPtr lParam);

Артем_2
Артем_2

Да, вот я думаю, может быть можно как-то кэшировать окна, а не производить посик каждый раз по всему списку открытых окон. На rsdn, конечно, тоже надо будет написать

sun
sun

А может спросить у Микрософта? Если кто может грамотно поставить вопрос. Мол, пацаны, такая хрень происходит, что на вин7 тормоза нереальные появляются, что думаете, куда смотреть и т.д.

Сижу на вин7, после 14.00 тестировать невозможно, время включения дде до 20 мин... а утром 2-5 мин!!! после 16.00 дде вообще не поднимется за какоето измеряемое время...

Maxim K.
Maxim K.

Странно, пользуюсь Win7, но экспорт стартует достаточно быстро (секунд 15 максимум, если по всем возможным таблицам) независимо от времени суток...

sun
sun

Я вам завидую. Но похоже проблема существует реально. Возможно дело в настройке вин7, возможно в связке с железом или что-то еще. У меня совершенно четкая связь времени суток и скорости вкллючения дде.

esper
esper

Использую Windows Server 2008R2 x64,старт экспорта конечно медленней чем на Win2003, но запуск проходит секунд за 30 максимум. Время запуска сильно зависит от количества открытых окон, а так же от количества вкладок в опере. Зависимости от времени суток нет.

Да, вот я думаю, может быть можно как-то кэшировать окна, а не производить посик каждый раз по всему списку открытых окон. На rsdn, конечно, тоже надо будет написать Так список открытых окон меняется и нужное нам окно открывается только перед самым поиском

Сижу на вин7, после 14.00 тестировать невозможно, время включения дде до 20 мин... а утром 2-5 мин!!! после 16.00 дде вообще не поднимется за какоето измеряемое время... А если попробовать перезагрузить компьютер и запустить экспорт, за сколько он пройдет? Можно еще попробовать отключить все навороты интерфейса и тоже замерить время старта экспорта.

Артем_2
Артем_2

Коллеги, проблема локализована(см. #28,#30), - это функция EnumWindows из user32.dll,которая фигово работает в виндоусе после висты. Сегодня я напишу письмо на форумах, с вопросом откуда такая несправедливость и есть ли достойные альтернативы. Если там не получится, то я за то, чтобы искать другое решение, т.к. очевидно проблему надо решать. Уверен, при содействии таких мастеров как Михаил и Александр решение обязательно найдется.

esper
esper

Артем_2: Коллеги, проблема локализована(см. #28,#30), - это функция EnumWindows из user32.dll,которая фигово работает в виндоусе после висты. Как писал выше, у меня на W2K8 все отрабатывает довольно быстро, у Maxim K. на Win7 тоже без задержек. Графический интерфейс у меня классический, у вас Aero? Много ли открытых окон или вкладок в браузере?

Сейчас отдельно проверил у себя время работы функции EnumWindows. Программа в аттаче, код следующий:

namespace ConsoleApplication3
{
	using System;
	using System.Diagnostics;
	using System.Runtime.InteropServices;

	internal class Program
	{
		#region Delegates

		public delegate bool CallBackPtr(int hwnd, int lParam);

		#endregion

		[DllImport("user32.dll")]
		public static extern int EnumWindows(CallBackPtr callPtr, int lPar);

		public static bool Handler(int hwnd, int lParam)
		{
			//Console.WriteLine("Window handle is " + hwnd);
			return true;
		}

		private static void Main(string[] args)
		{
			var watch = Stopwatch.StartNew();

			EnumWindows(Handler, 0);

			watch.Stop();
			Console.WriteLine("Total time: {0}", watch.Elapsed);

			Console.ReadLine();
		}
	}
}

На Windows Server 2008R2 x86 он выполняется за "Total time: 00:00:00.0009447". Что программа выведет у вас?

Артем_2
Артем_2

Уменя На w7 x86 за "Total time: 00:00:00.0008483".

esper
esper

Артем_2: Уменя На w7 x86 за "Total time: 00:00:00.0008483". Тогда почему вы решили, что тормозит именно эта функция?

Артем_2
Артем_2

Потому что она вызывается в #28. Но конкретно по EnumWindows я замеры не делал, т.к. замучился в исследовниях и как-то решил, что дело именно в ней, раз она ключевая в FilterToplevelWindows да и проблема привязана к платформе


 public static SystemWindow[] FilterToplevelWindows(Predicate<SystemWindow> predicate)
        {
            List<SystemWindow> wnds = new List<SystemWindow>();
            SystemWindow.EnumWindows((SystemWindow.EnumWindowsProc)((hwnd, lParam) =>
            {
                SystemWindow local_0 = new SystemWindow(hwnd);
                if (predicate(local_0))
                    wnds.Add(local_0);
                return 1;
            }), new IntPtr(0));
            return wnds.ToArray();
        }

esper
esper

Артем_2: Потому что она вызывается в #28. Но конкретно по EnumWindows я замеры не делал, т.к. замучился в исследовниях и как-то решил, что дело именно в ней, раз она ключевая в FilterToplevelWindows да и проблема привязана к платформе

Откуда вызывается FilterToplevelWindows? Из SystemWindow.AllToplevelWindows? Возьмем следующий пример:

namespace ConsoleApplication3
{
	using System;
	using System.Diagnostics;
	using System.Runtime.InteropServices;
	using ManagedWinapi.Windows;

	internal class Program
	{
		#region Delegates

		public delegate bool CallBackPtr(int hwnd, int lParam);

		#endregion

		[DllImport("user32.dll")]
		public static extern int EnumWindows(CallBackPtr callPtr, int lPar);

		private static void Main(string[] args)
		{
			var watch = Stopwatch.StartNew();
			
			var windowsCount = 0;
			EnumWindows((hwnd, lParam) =>
			{
				windowsCount++;
				return true;
			}, 0);
			
			watch.Stop();
			Console.WriteLine("EnumWindows time: {0} Windows count: {1}", watch.Elapsed, windowsCount);

			watch = Stopwatch.StartNew();
			var wins = SystemWindow.AllToplevelWindows;
			watch.Stop();
			Console.WriteLine("AllToplevelWindows time: {0} Windows count: {1}", watch.Elapsed, wins.Length);

			Console.ReadLine();
		}
	}
}

Вывод:

EnumWindows time: 00:00:00.0014409 Windows count: 374 AllToplevelWindows time: 00:00:00.0024402 Windows count: 374

Артем_2
Артем_2

При этом время увеличивапется, если добавить условие на Linq

var wins = SystemWindow.AllToplevelWindows.Where(w=>w.Process.Id == AppDomain.GetCurrentThreadId()).ToArray();
, тогда

EnumWindows time: 00:00:00.0009348 Windows count: 730 AllToplevelWindows time: 00:00:00.9365030 Windows count: 0

Видать, зря я EnumWindows так катигорично забраковал

esper
esper

Артем_2: При этом время увеличивапется, если добавить условие на Linq

var wins = SystemWindow.AllToplevelWindows.Where(w=>w.Process.Id == AppDomain.GetCurrentThreadId()).ToArray();

У меня это условие не очень сильно увеличивает время

EnumWindows time: 00:00:00.0014281 Windows count: 384 AllToplevelWindows time: 00:00:00.2985305 Windows count: 0

Вообще, дело тут не в LINQ, дело в том, что SystemWindow.Process выполняет пару дополнительных действий, в частности тормозит Process.GetProcessById

namespace ConsoleApplication3
{
	using System;
	using System.Diagnostics;
	using System.Linq;
	using System.Runtime.InteropServices;
	using ManagedWinapi.Windows;

	internal class Program
	{
		#region Delegates

		public delegate bool CallBackPtr(int hwnd, int lParam);

		#endregion

		[DllImport("user32.dll")]
		public static extern int EnumWindows(CallBackPtr callPtr, int lPar);

		[DllImport("user32.dll", SetLastError = true)]
		static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

		static int GetProcessId(IntPtr hwnd)
		{
			int pid;
			GetWindowThreadProcessId(hwnd, out pid);
			//Process.GetProcessById(pid);
			return pid;
		}

		private static void Main()
		{
			var watch = Stopwatch.StartNew();
			
			var windowsCount = 0;
			EnumWindows((hwnd, lParam) =>
			{
				windowsCount++;
				return true;
			}, 0);
			
			watch.Stop();
			Console.WriteLine("EnumWindows time: {0} Windows count: {1}", watch.Elapsed, windowsCount);

			watch = Stopwatch.StartNew();
			//var wins = SystemWindow.AllToplevelWindows.Where(w => w.Process.Id == AppDomain.GetCurrentThreadId()).ToArray();
			var wins = SystemWindow.FilterToplevelWindows(w => GetProcessId(w.HWnd) == AppDomain.GetCurrentThreadId());
			watch.Stop();
			Console.WriteLine("AllToplevelWindows time: {0} Windows count: {1}", watch.Elapsed, wins.Length);

			Console.ReadLine();
		}
	}
}

P.s. посмотреть бы как это все используется в S#... Alexander, можете показать эту часть исходника?

Alexander
Alexander

esper: P.s. посмотреть бы как это все используется в S#... Alexander, можете показать эту часть исходника?

Оставьте почту, отправлю весь QuikTerminal

Alexander
Alexander

esper: Вообще, дело тут не в LINQ, дело в том, что SystemWindow.Process выполняет пару дополнительных действий, в частности тормозит Process.GetProcessById

А после такого измения кода как быстро стало отрабатывать?

Alexander
Alexander

У меня это условие не очень сильно увеличивает время

EnumWindows time: 00:00:00.0014281 Windows count: 384 AllToplevelWindows time: 00:00:00.2985305 Windows count: 0

В 100 раз. Довольно сильно :)

esper
esper

Alexander: Оставьте почту, отправлю весь QuikTerminal отправил в личку

Alexander: Это понятно... Время тратится на доступ к w.Process (см. #44) Я вот и говорю, может надо типа того че-то сделать Если просто попробовать поменять предикат, как в предыдущем моем сообщении?

esper
esper

Alexander: А после такого измения кода как быстро стало отрабатывать?

С измененным предикатом:

EnumWindows time: 00:00:00.0018250 Windows count: 393 AllToplevelWindows time: 00:00:00.0037758 Windows count: 0

без:

EnumWindows time: 00:00:00.0012580 Windows count: 393 AllToplevelWindows time: 00:00:00.3220401 Windows count: 0

Артем_2
Артем_2

Видимо, время тратится на доступ к w.Process

Может быть тогда можно попробовать для получения окон квика сначала ограничить выборку из AllToplevelWindows по какому-нить нетормозному признаку (по ClassName или еще как), а потом уже фильтровать по w.Process

Артем_2
Артем_2

Вообще, дело тут не в LINQ, дело в том, что SystemWindow.Process выполняет пару дополнительных действий, в частности тормозит Process.GetProcessById Это понятно... Время тратится на доступ к w.Process (см. #44) Я вот и говорю, может надо типа того че-то сделать:



 var wins = SystemWindow.AllToplevelWindows.Where(w => w.ClassName.Contains("VBF")).Where(w => w.Process.Id == AppDomain.GetCurrentThreadId());

Эх, нету ни квика ни кода из QuikTerminal сейчас под рукой чтоб проверить😭

Артем_2
Артем_2

У меня это условие не очень сильно увеличивает время

Цитата: EnumWindows time: 00:00:00.0014281 Windows count: 384 AllToplevelWindows time: 00:00:00.2985305 Windows count: 0 У вас окон 384 выводится, а у меня больше 700

Артем_2
Артем_2

Я не сразу допер... С новым предикатом ведь совсем все замечательно!!!🤤

esper
esper

Александр, можете попробовать собрать проект с такой вот функцией GetQuikWindows:

[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

static int GetProcessId(IntPtr hwnd)
{
	int pid;
	GetWindowThreadProcessId(hwnd, out pid);
	return pid;
}

private static IEnumerable<SystemWindow> GetQuikWindows(Process process)
{
	if (process == null)
		throw new ArgumentNullException("process");

	return SystemWindow.FilterToplevelWindows(q => GetProcessId(q.HWnd) == process.Id);
}
Артем_2 Den
Артем_2
Артем_2

Получилось чего-нить?

Alexander
Alexander

На моей машине (Win 7) стало запускаться раз в 10 быстрее - я банально даже не успеваю просмотреть окошки. Вы большие молодцы, спасибо! 👍

После закрытия основной сессии протестирую с 7 копиями квиков.

Alexander
Alexander

Exception возник при остановке экспорта. Буду разбираться.

В любом случае - запуск \ остановка стала на порядки быстрее :)

Артем_2
Артем_2

Урааа!😀 Отдельное спасибо esper!

Alexander
Alexander

Exception поборол, в 3.2.6 будет это изменение.

Den
Den
Den

Alexander: Exception поборол, в 3.2.6 будет это изменение. Спасибо большое! Теперь экспорт просто летает!!!

vvt
vvt 作者

Ура!!! Свершилось!!! Спасибо!!!