Подключение к Quik и запуск DDE
Atom Ответить
24.01.2011


vvt

Фотография
Пробую подключение к 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 Ответов
< 1 2 3  >
Alexander

Фотография
Дата: 14.07.2011
Ответить


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

Артем_2

Фотография
Дата: 14.07.2011
Ответить


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

Код

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();
        }


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

Артем_2

Фотография
Дата: 14.07.2011
Ответить


А EnumWindows - это Api
Код

    [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static bool EnumWindows(SystemWindow.EnumWindowsProc lpEnumFunc, IntPtr lParam);
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 14.07.2011
Ответить


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

...

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


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

Артем_2

Фотография
Дата: 14.07.2011
Ответить


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

sun

Фотография
Дата: 15.07.2011
Ответить


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

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

Maxim K.

Фотография
Дата: 15.07.2011
Ответить


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

sun

Фотография
Дата: 15.07.2011
Ответить


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

esper

Фотография
Программист
Дата: 15.07.2011
Ответить


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

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

Так список открытых окон меняется и нужное нам окно открывается только перед самым поиском

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

А если попробовать перезагрузить компьютер и запустить экспорт, за сколько он пройдет? Можно еще попробовать отключить все навороты интерфейса и тоже замерить время старта экспорта.
Спасибо:

Артем_2

Фотография
Дата: 18.07.2011
Ответить


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

esper

Фотография
Программист
Дата: 18.07.2011
Ответить


Артем_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

Фотография
Дата: 18.07.2011
Ответить


Уменя На w7 x86 за "Total time: 00:00:00.0008483".
Спасибо:

esper

Фотография
Программист
Дата: 18.07.2011
Ответить


Артем_2 Перейти
Уменя На w7 x86 за "Total time: 00:00:00.0008483".

Тогда почему вы решили, что тормозит именно эта функция?
Спасибо:

Артем_2

Фотография
Дата: 18.07.2011
Ответить


Потому что она вызывается в #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

Фотография
Программист
Дата: 18.07.2011
Ответить


Артем_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
ManagedWinapi.zip 46,8KB (0)
Спасибо:

Артем_2

Фотография
Дата: 18.07.2011
Ответить


При этом время увеличивапется, если добавить условие на 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 так катигорично забраковал
Спасибо:

Артем_2

Фотография
Дата: 18.07.2011
Ответить


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

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

esper

Фотография
Программист
Дата: 18.07.2011
Ответить


Артем_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

Фотография
Дата: 18.07.2011
Ответить


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


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

Артем_2

Фотография
Дата: 18.07.2011
Ответить


Цитата:

Вообще, дело тут не в 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 сейчас под рукой чтоб проверитьCrying
Спасибо:

Alexander

Фотография
Дата: 18.07.2011
Ответить


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


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

Артем_2

Фотография
Дата: 18.07.2011
Ответить


Цитата:

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

Цитата:
EnumWindows time: 00:00:00.0014281 Windows count: 384
AllToplevelWindows time: 00:00:00.2985305 Windows count: 0

У вас окон 384 выводится, а у меня больше 700
Спасибо:

Alexander

Фотография
Дата: 18.07.2011
Ответить


esper Перейти
У меня это условие не очень сильно увеличивает время
Цитата:
EnumWindows time: 00:00:00.0014281 Windows count: 384
AllToplevelWindows time: 00:00:00.2985305 Windows count: 0



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

esper

Фотография
Программист
Дата: 18.07.2011
Ответить


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

отправил в личку

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

Если просто попробовать поменять предикат, как в предыдущем моем сообщении?
Спасибо:

esper

Фотография
Программист
Дата: 18.07.2011
Ответить


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
Спасибо:
< 1 2 3  >

Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy