Перейти к содержимому

Фотография

Ожидание загрузки содержимого грида


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 23

#1 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 07 апреля 2009 - 14:58

Стоит задача написать функцию ожидания загрузки содержимого грида. Проект .Net
Форма состоит из 3х таблиц. При открытии формы все таблицы последовательно загружаются данными. Таблица, над которой необходимо производить действия загружается в последнюю очередь. Соответственно, чем больше данных тем дольше происходит подгрузка данных из БД. Сколько строк таблицы должно загрузиться заведомо неизвестно, поэтому использовать Delay нельзя (в данный момент время загрузки составляет от 30 секунд)

Каким методом можно узнать что грид полностью создался?
Сейчас стоит следующая проверка:
1. Ожидание создания WinForms объекта
obj.WaitWinFormsObject(name, timeout);
2. Ожидание создания грида
while ((!NameMapping.Sys.MyApp.MyFrame.MdiClient.WaitNamedChild("dgvQueue", 3000).Exists) && (timeout-- > 0))
{
	Aliases.MyFrame.RefreshMappingInfo();
}

Проблема в том, что данная проверка срабатывает не всегда:
* Frame создается, но маппинг не подтягивается (RefreshMappingInfo() не помогает)
* при проверке №2 TC выдает ошибку "an error occured" с описанием:

Possible reasons:
1. The application stopped responding.
2. The application was compiled incorrectly (see the Open Applications topic in the help system).
3. An error occurred in TestComplete.

Technical information:
176 0x8001011f (Возврат из операции произошел из-за превышения времени ожидания.)

Sys.Process("MyApp").WinFormsObject("MyFrame").WinFormsObject("MdiClient").WinFormsObject("dgvQueue")


  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#2 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 08 апреля 2009 - 03:52

Здравствуйте.

А если так?
while ((!NameMapping.Sys.MyApp.MyFrame.MdiClient.WaitNamedChild("dgvQueue", 3000).Exists) && (timeout-- > 0))
{
	NameMapping.Sys.MyApp.MyFrame.MdiClient.RefreshMappingInfo();
}

  • 0
С уважением,
Дмитрий

#3 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 08 апреля 2009 - 06:56

Не помогает
  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#4 Drakon

Drakon

    Новый участник

  • Members
  • Pip
  • 20 сообщений

Отправлено 08 апреля 2009 - 08:39

Как я понимаю, нужно дождаться завершения загрузки данных в последнюю таблицу (грид)... на сколько я знаю, стандартные свойства грида этого сделать не позволяют.

Могу предложить такой вариант:
1. Дождемся начала заполнения нужного грида (проверяем либо RowCount грида либо на отсутствие текста в первой ячейке).
2. После того, как дождались, берем у грида RowCount, запоминаем, делаем Delay (например, на 5 секунд), сверяем RowCount текущий с тем что запомнили. Если одинаковы - считаем грид заполненным, иначе, запускаем цикл заново.
  • 0

#5 Den_BOLV

Den_BOLV

    Новый участник

  • Members
  • Pip
  • 32 сообщений
  • ФИО:Васильченко Денис Петрович


Отправлено 08 апреля 2009 - 09:06

Наше приложение часто читает из базы, работает с аппсервером, то есть есть операции, занимающие много времени, и нужно дождаться пока приложение будет готово для выполнения следующих действий. Мы выходим из положения следующим образом: сначала ждем пока процесс приложения станет idle, потом уже проверяем конкретное окно. Логика следующая - пока приложения что-то там делает - читает из базы, пересчитывает, заполняет свои структуры и тд - процесс занят. Он будет idle когда все эти операции закончены. Используются Win32API.OpenProcess() и Win32API.WaitForInputIdle().
  • 0

#6 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 08 апреля 2009 - 11:18

Спасибо, сейчас попробую.
Пока остается открытым вопрос с маппингом. 1-2 раза из 10 объект перестает распознаваться как замаппленный. Путь до грида намного длиннее, чем я привел в первом примере:
Sys.MyApp.frmMain.MdiClient.frmValidation.MainSplitContainer.SplitterPanel.
pnlMiddle.pnlMain.splitContainer1.SplitterPanel1.m_ValidationQueue.splitMain.SplitterPanel1.dgvQueue

Проблемы начинаются на сплиттерах, т.е. то не распознается SplitterPanel1, то splitMain (в зависимости от запуска).
Сколько (по опыту) занимает выполнение RefreshMappingInfo()? При вызове этого метода происходит обновление маппинга одного дочернего объекта или всего дерева объекта?
  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#7 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 08 апреля 2009 - 11:46

Дальнейшее исследование показало, что временами у сплиттера меняется имя класса:
то WindowsForms10.Window.8.app.0.143da96, то WindowsForms10.Window.8.app.0.143da961

Почему он не распознается я не совсем понимаю, так как в маппинге выбрано свойство Name: WinFormsObject("SplitterPanel", "", 1) и какой там класс формы должно быть все равно :crazy: ... потому refreshmappinginfo и не помогал

Есть идея перенести имя класса в Selected Properties и задать ему: WindowsForms10.Window.8.app.0.*
  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#8 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 08 апреля 2009 - 12:50

Наше приложение часто читает из базы, работает с аппсервером, то есть есть операции, занимающие много времени, и нужно дождаться пока приложение будет готово для выполнения следующих действий. Мы выходим из положения следующим образом: сначала ждем пока процесс приложения станет idle, потом уже проверяем конкретное окно. Логика следующая - пока приложения что-то там делает - читает из базы, пересчитывает, заполняет свои структуры и тд - процесс занят. Он будет idle когда все эти операции закончены. Используются Win32API.OpenProcess() и Win32API.WaitForInputIdle().


Как я понял необходимо сделать следующие действия:
var id = Win32API.GetCurrentProcessId()
var handle = Win32API.OpenProcess(0, false, id);
Win32API.WaitForInputIdle(handle, INFINITE);

idle происходит мгновенно, но приложением в данный момент времени ничего делать нельзя
  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#9 Den_BOLV

Den_BOLV

    Новый участник

  • Members
  • Pip
  • 32 сообщений
  • ФИО:Васильченко Денис Петрович


Отправлено 08 апреля 2009 - 13:22

Наше приложение часто читает из базы, работает с аппсервером, то есть есть операции, занимающие много времени, и нужно дождаться пока приложение будет готово для выполнения следующих действий. Мы выходим из положения следующим образом: сначала ждем пока процесс приложения станет idle, потом уже проверяем конкретное окно. Логика следующая - пока приложения что-то там делает - читает из базы, пересчитывает, заполняет свои структуры и тд - процесс занят. Он будет idle когда все эти операции закончены. Используются Win32API.OpenProcess() и Win32API.WaitForInputIdle().


Как я понял необходимо сделать следующие действия:
var id = Win32API.GetCurrentProcessId()
var handle = Win32API.OpenProcess(0, false, id);
Win32API.WaitForInputIdle(handle, INFINITE);

idle происходит мгновенно, но приложением в данный момент времени ничего делать нельзя


наш код такой:

//Waits until the process becomes idle;
//Timeout: time to wait, msecs;
//Proc: Process object;
//Returns 0 if process is idle, null in case of error.
//Returns 1 or -1 (??) if process is busy during timeout.
function TCSIsProcessIdle(Proc, Timeout)
{
try
{
var pHandle = Win32API.OpenProcess(PROCESS_ALL_ACCESS, false, Proc.ProcessID);
var res = Win32API.WaitForInputIdle(pHandle, Timeout);
return res;
}
catch(e)
{
return null;
}
}
  • 0

#10 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 09 апреля 2009 - 07:02

Результат такой же, независимо от timeout в WaitForInputIdle() ожидания загрузки грида не происходит.
  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#11 Kuhtich

Kuhtich

    Новый участник

  • Members
  • Pip
  • 9 сообщений

Отправлено 09 апреля 2009 - 07:09

Результат такой же, независимо от timeout в WaitForInputIdle() ожидания загрузки грида не происходит.

У меня такой же результат. Независимо от того, "висит" приложение, ожидая ответа бд, или нет, WaitForInputIdle() всегда выдает 0.
  • 0

#12 Drakon

Drakon

    Новый участник

  • Members
  • Pip
  • 20 сообщений

Отправлено 09 апреля 2009 - 08:32

Проблемы начинаются на сплиттерах, т.е. то не распознается SplitterPanel1, то splitMain (в зависимости от запуска).
Сколько (по опыту) занимает выполнение RefreshMappingInfo()? При вызове этого метода происходит обновление маппинга одного дочернего объекта или всего дерева объекта?

Могу предположить, что объекты SplitterPanel1 и splitMain замапированны по не стабильным свойствам.

Дальнейшее исследование показало, что временами у сплиттера меняется имя класса:
то WindowsForms10.Window.8.app.0.143da96, то WindowsForms10.Window.8.app.0.143da961

Почему он не распознается я не совсем понимаю, так как в маппинге выбрано свойство Name: WinFormsObject("SplitterPanel", "", 1) и какой там класс формы должно быть все равно ... потому refreshmappinginfo и не помогал

Name и WndClass - не самые подходящие свойства для мапирования .NET контрола. Советую использовать св-во NativeClrObject.Name и/или WndCaption (если оно не меняется).

Сколько (по опыту) занимает выполнение RefreshMappingInfo()? При вызове этого метода происходит обновление маппинга одного дочернего объекта или всего дерева объекта?

Этот метод проверяет правильность ссылки на объект у которого мы зовем этот метод. Т.е. проверяет все ноды в дереве выше объекта.
Метод работает довольно быстро.
  • 0

#13 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 09 апреля 2009 - 08:46

Проблемы начинаются на сплиттерах, т.е. то не распознается SplitterPanel1, то splitMain (в зависимости от запуска).
Сколько (по опыту) занимает выполнение RefreshMappingInfo()? При вызове этого метода происходит обновление маппинга одного дочернего объекта или всего дерева объекта?

Могу предположить, что объекты SplitterPanel1 и splitMain замапированны по не стабильным свойствам.


Сплиттеры замаппированы по стабильным свойствам, Name всегда одно и тоже (проверено).

Дальнейшее исследование показало, что временами у сплиттера меняется имя класса:
то WindowsForms10.Window.8.app.0.143da96, то WindowsForms10.Window.8.app.0.143da961

Почему он не распознается я не совсем понимаю, так как в маппинге выбрано свойство Name: WinFormsObject("SplitterPanel", "", 1) и какой там класс формы должно быть все равно ... потому refreshmappinginfo и не помогал

Name и WndClass - не самые подходящие свойства для мапирования .NET контрола. Советую использовать св-во NativeClrObject.Name и/или WndCaption (если оно не меняется).


NativeClrObject.Name и WndCaption у сплиттеров отсутствуют.


Сколько (по опыту) занимает выполнение RefreshMappingInfo()? При вызове этого метода происходит обновление маппинга одного дочернего объекта или всего дерева объекта?

Этот метод проверяет правильность ссылки на объект у которого мы зовем этот метод. Т.е. проверяет все ноды в дереве выше объекта.
Метод работает довольно быстро.

Спасибо
  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#14 Paulitto

Paulitto

    Новый участник

  • Members
  • Pip
  • 39 сообщений

Отправлено 14 апреля 2009 - 07:31

Насчет проблемы с ожиданием загрузки - я решал ее следующим образом
Когда в грид загружается очч много данных приложение подвисает - и в этот момент в ObjectBrowser под процессом Explorer появляется окно класса "Ghost". Ждать нужно ровно столько сколько оно существует:

while (Sys["process"]("Explorer")["WaitWindow"]("Ghost", <название приложения>) ["Exists"]())
BuiltIn.Delay(1000);

Надеюсь поможет
  • 0

#15 Kuhtich

Kuhtich

    Новый участник

  • Members
  • Pip
  • 9 сообщений

Отправлено 16 апреля 2009 - 07:50

Придумал как вариант:
do while 1
If Sys.Process(<Process Name>).CPUUsage = 0 Then
Exit do
End If
Sleep(1000)
loop
Если задать условием цикла, то у меня глючит, поэтому цикл бесконечный.
  • 0

#16 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 20 апреля 2009 - 13:18

Насчет проблемы с ожиданием загрузки - я решал ее следующим образом
Когда в грид загружается очч много данных приложение подвисает - и в этот момент в ObjectBrowser под процессом Explorer появляется окно класса "Ghost". Ждать нужно ровно столько сколько оно существует:

while (Sys["process"]("Explorer")["WaitWindow"]("Ghost", <название приложения>) ["Exists"]())
BuiltIn.Delay(1000);

Надеюсь поможет


Не помогло. Внутрь цикла ТС даж не заходит
  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#17 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 20 апреля 2009 - 13:24

Придумал как вариант:
do while 1
If Sys.Process(<Process Name>).CPUUsage = 0 Then
Exit do
End If
Sleep(1000)
loop
Если задать условием цикла, то у меня глючит, поэтому цикл бесконечный.


Пока происходит загрузка грида CPU не используется.. Точнее скачет 0-1% и частенько сразу попадаем на 0.
  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#18 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 20 апреля 2009 - 13:26

Пока проблему решил следующим образом:
function WaitForFillingDGV(ParentObj, dgvObj, childName, timeout)
{
	if (!timeout)
		timeout = 60; //секунд
	t1 = new PerformanceCounter();
	t1.Now;

	IsProcessIdle();  //функция описывалась ранее в теме
	while ((!ParentObj.WaitNamedChild(childName, 3000).Exists) && (timeout-- >0))
	{
		ParentObj.RefreshMappingInfo();
	}
	if (timeout == 0) Log.Message('Объекта не дождались');
	
	tmp = 0;
	timeout = 60;
	IsProcessIdle();		
	
	while ((dgvObj.wRowCount == 0) && (timeout-- >0)) //dgv создался, ждем загрузки строк
	{ 
	   aqUtils.Delay(1000);
	}
  
  if (timeout == 0) 
	{
		Log.Message('Объекта не дождались или строк нет');
		t1.Delta();
		Log.Message('Ждали загрузки ' + t1.sum + 'секунд');
		return -1;
	}
	
	IsProcessIdle();	  
	while (tmp != dgvObj.wRowCount) //проверяем строки еще загружаются или процесс остановился
	{
		tmp = dgvObj.wRowCount; 
		aqUtils.Delay(1000);									
	}   
	t1.Delta();
	Log.Message('Grid загружался в течении ' + t1.sum + ' секунд');
	return 0;	  
}

Тем не менее, в лог частенько пишется

Possible reasons:
1. The application stopped responding.
2. The application was compiled incorrectly (see the Open Applications topic in the help system).
3. An error occurred in TestComplete.

Technical information:
176 0x8001011f (Возврат из операции произошел из-за превышения времени ожидания.)

Иногда этот RuntimeError останавливает выполнение скрипта.
  • 0
Если ничего не помогает, прочтите наконец инструкцию!

#19 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 21 апреля 2009 - 06:06

Здравствуйте.

Кстати, а что за грид? Какого типа, кто производитель?
  • 0
С уважением,
Дмитрий

#20 DrBlast

DrBlast

    Активный участник

  • Members
  • PipPip
  • 139 сообщений
  • ФИО:Евгений
  • Город:Москва

Отправлено 21 апреля 2009 - 06:54

Здравствуйте.

Кстати, а что за грид? Какого типа, кто производитель?



Стандартный DataGridView от Microsoft (.Net 2.0)
  • 0
Если ничего не помогает, прочтите наконец инструкцию!


Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных