powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / OLAP и DWH [игнор отключен] [закрыт для гостей] / ADOMD.NET 9.0: XmlaReader.Close() зависает с AS2000
4 сообщений из 4, страница 1 из 1
ADOMD.NET 9.0: XmlaReader.Close() зависает с AS2000
    #33733907
Ihor Bobak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача: прервать выполнение AdomdCommand.ExecuteXmlReader().

Последовательность действий:
В одном потоке делаю AdomdCommand.ExecuteXmlReader(), потом в цикле
читаю этот ридер, за 10 секунд после него другой поток обрывает первый
(Thread.Abort). Попадаем в finally, где вызывается reader.Close(), который
работает очень долго - в этом и проблема.

Обнаружено:
Начал копать на чем зависает reader.Close(), и вижу последовательность:
XmlaReader.Close(), XmlaReader.ReturnReader(), XmlaClient.EndReceival(),
IXMLAStream.Skip(), ну а в нем вот это:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
public override void Skip()
{
	if (base.disposed)
	{
		throw new ObjectDisposedException(null);
	}
	try
	{
		if (this.readStream != null)
		{
			// Вот здесь оно висит
			while (this.readStream.Read(IXMLAStream.bufferForSkip,  0 , 0x2000) >  0 )
			{
			}
			this.readStream.Close();
			this.readStream = null;
		}
		if (this.writeStream != null)
		{
			this.writeStream.Close();
			this.writeStream = null;
		}
	}

Вопросы:

1) Зачем нам делать вычитывание всего этого ненужного контента
в цикле while? Ведь readStream потом все-равно закроют, и все, что оттуда
вычитали, никем не будет использовано.

2) Можно ли безболезненно удалить этот (на первый взгляд) ненужный цикл?
Или существует способ получше для того, чтобы прервать AdomdCommand.ExecuteXmlReader()?
...
Рейтинг: 0 / 0
ADOMD.NET 9.0: XmlaReader.Close() зависает с AS2000
    #33750027
Ihor Bobak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пример крупной утечки памяти с ADOMD.NET 8.0. AS2000, база FoodMart 2000. В цикле запускаем поток, ждем 5 секунд, abort-аем поток. В потоке устанавливаем коннект, открываем ридер, начинаем читать, и если оборвали - не закрываем ридер, так как будет КОНКРЕТНЫЙ тормоз (почему - см. выше).

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
using System;
using System.Threading;
using System.Xml;
using Microsoft.AnalysisServices.AdomdClient;

namespace AdomdMemotyLeakTest
{
	class Program
	{
		static void Main(string[] args)
		{
			for (int i =  0 ; i <  1000 ; ++i)
			{
				Thread t = new Thread(new ThreadStart(RunTest2));
				t.Start();
				Thread.Sleep( 5000 );
				t.Abort();
				Console.WriteLine("Launch: {0}", i);
			}
			Console.ReadLine();
		}


		static void RunTest2()
		{
			Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
			Thread.CurrentThread.SetApartmentState(ApartmentState.MTA);
			
			AdomdConnection conn = new AdomdConnection("Data Source=localhost;Catalog=FoodMart 2000;ConnectTo=8.0");
			bool aborted = false;
			XmlReader reader = null;
			try
			{
				AdomdCommand command = conn.CreateCommand();
				command.CommandText =
					@"
select 
{{[Product].[Product Name].Members} * 
{[Customers].[Name].Members}}
 on columns,
[Store].[Store Name].Members on rows
from sales				
				";
				conn.Open();
				reader = command.ExecuteXmlReader();
				while (reader.Read())
					Thread.Sleep( 68 );
			}
			catch (ThreadAbortException)
			{
				aborted = true;
			}
			finally
			{
				if (!aborted)
					reader.Close();
				try
				{
					conn.Close();	
				}
				catch (Exception ex)
				{
					Console.WriteLine("Exception: {0}", ex.Message);
				}
			}
			GC.Collect();
		}
	}
}

И наблюдаем вот такую картину:

0) если поток обрывается на момент выполнения XmlaReader.Read(), то срабатывает XmlaReader.HandleException который успешно сделает XmlaClient.Disconnect(endsession=false). Тот в свою очередь вызовет CloseAll, дальше IXmlaStream.Dispose(), ну а тот закроет все стримы построенные на COM (NativeIStream и пр.). Проблема: память при этом ДАЖЕ НЕ ДУМАЕТ освобождаться.

1) если поток обрывается на момент выполнения действия после Read (в демонстрационном коде - Thread.Sleep(68)), то connection.Close() вылетает с грохотом "The connection cannot be used while an XMLReader object is open". А почему? А потому в отличие от предыдущего случае идет вызов XmlaClient.Disconnect(endsession=true) -> XmlaClient.EndSession, который естественно отваливается ибо ридер еще открыт.

2) AdomdCommand.Cancel, вызваннае как перед Thread.Abort, так и внутри, не помогает - матерится "the session sddsf384932jdsdasff does not exist" если поток обрывается на момент XmlaReader.Read.

А в чем же задача? В том, чтобы в реальной апликации оборвать выполнение запроса, когда пользователь нажал на кнопку Cancel.

Так вот, если обрывать поток, то память не освобождается. Даже несмотря на то, что теоретически все закрыто. Если запустить вышеуказанный пример, то можно наблюдать как размер памяти, занимаемой процессом, все пухнет, пухнет, пухнет, пока не зажрет все и не вылетит "you are out of virtual memory". .NET Memory Profiler показывает, что проблема как раз в native memory. Похоже на то, что если не выкачать из ридера все то, что пользователю 100 лет не нужно (ибо он нажал Cancel), то даже несмотря на все вызовы Marshal.ReleaseComObject(this.nativeIStream) native memory не освобождается, и все тут.

Короче, люди добрые, у меня полный стопор. Надо оборвать выполнение команды, да так, чтобы вся память ОСВОБОДИЛАСЬ, и чтобы сам процесс обрыва ПРОХОДИЛ МГНОВЕННО.

Буду очень благодарен за любые советы.
...
Рейтинг: 0 / 0
ADOMD.NET 9.0: XmlaReader.Close() зависает с AS2000
    #33750046
Владимир Штепа
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы какой XMLA провайдер используете? IXMLA? Тот что в вашем же процессе живет?

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


BobakNET Memory Profiler показывает, что проблема как раз в native memory. Похоже на то, что если не выкачать из ридера все то, что пользователю 100 лет не нужно (ибо он нажал Cancel), то даже несмотря на все вызовы Marshal.ReleaseComObject(this.nativeIStream) native memory не освобождается, и все тут.

Так оно и было. Запрос выполняется на стороне клиента, в адресном вашего процесса. То что вы со сторны .Net обрубили все концы для PTS ничего не значит - он продолжает выполнять запрос и заполнять ячейки. А то что вы их не читаете - это не его проблема. Он крутся дальше.

Единственная рекомендация - держать IXMLA в отдельном процессе, и если надо обрубить запрос, надо убивать этот процесс. Но и это не факт что поможет - в зависимости от характера MDX запроса сам AS2000 может дальше выполнять этот запрос и ему будет начхать на то, что PTS клиент ушел в небытие. Это же Shilon - C'est la vie.
...
Рейтинг: 0 / 0
ADOMD.NET 9.0: XmlaReader.Close() зависает с AS2000
    #33750050
Ihor Bobak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
backfireВы какой XMLA провайдер используете? IXMLA? Тот что в вашем же процессе живет?
так и есть.

backfireИсходя из собственного опыта - бросте вы эту идею - аккуратно освобождать память. Я бился над этой затеей не одну неделю. Ничего путнего не вышло.
И что посоветуете делать? Выносить в отдельный процесс?
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / OLAP и DWH [игнор отключен] [закрыт для гостей] / ADOMD.NET 9.0: XmlaReader.Close() зависает с AS2000
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]