WCF и IDisposable
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 11.05.17 03:41
Оценка:
Наткнулся тут на один метод в WCF-сервисе, который возвращает DataTable, а это Disposable тип. И что-то я призадумался.. А кто и как должен запускать Dispose у таких объектов? Делается ли это по какому-то волшебству автоматически? Или нужно в явном виде делать Dispose после возвращения (в finally?..)
Может там настройки какие-то или параметры вроде AutoDispose нужны?
Подскажите, если кто сталкивался.

Вообще я подумываю убрать этот DataTable оттуда, ибо нефиг. Но это долгий процесс, сейчас нужно убедиться, что там ресурсы не текут.
С уважением, Artem Korneev.
Re: WCF и IDisposable
От: Sinix  
Дата: 11.05.17 04:07
Оценка: 25 (5)
Здравствуйте, Artem Korneev, Вы писали:

AK>Наткнулся тут на один метод в WCF-сервисе, который возвращает DataTable, а это Disposable тип.

Ниччего страшного.

http://stackoverflow.com/questions/18869079/datatable-dispose-will-make-it-remove-from-memory

DataSet and DataTable don't actually have any unmanaged resources, so Dispose() doesn't actually do much. The Dispose() methods in DataSet and DataTable exists ONLY because of side effect of inheritance — in other words, it doesn't actually do anything useful in the finalization.

It turns out that DataSets, DataViews, DataTables suppress finalization in their constructors this is why calling Dispose() on them explicitly does nothing.


Ну и почему оно нужно было, тот же ответ:

Without a doubt, Dispose should be called on any Finalizable objects.
DataTables are Finalizable.
Calling Dispose significantly speeds up the reclaiming of memory.
MarshalByValueComponent calls GC.SuppressFinalize(this) in its Dispose() — skipping this means having to wait for dozens if not hundreds of Gen0 collections before memory is reclaimed.


Смысл в чём: MarshalByValueComponent (базовый тип DataTable/DataSet) имеет финалайзер и реализует IDisposable. По умолчанию любой наследник этого типа не может быть пожран GC сразу, нужно вызвать финализатор => объект переживает сборку мусора и будет собран только при уборке следующего поколения. Для датасетов это явно не лучшее решение, надеюсь, не надо объяснять, почему?

В качестве workaround конструктор датасета вызывает Gc.SuppressFinalise(), как бы намекая рантайму, что финалайзер не нужен. Благодаря этой нехитрой магии DataSet/DataTable собираются сразу, не дожидаясь вызова финалайзера и не засоряют память своими очень важными килобайтами.

Немножко более подробный ответ, http://stackoverflow.com/a/1603516
Re[2]: WCF и IDisposable
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 11.05.17 07:19
Оценка:
Здравствуйте, Sinix, Вы писали:

AK>>Наткнулся тут на один метод в WCF-сервисе, который возвращает DataTable, а это Disposable тип.

S>Ниччего страшного.
[...]
S>MarshalByValueComponent calls GC.SuppressFinalize(this) in its Dispose() — skipping this means having to wait for dozens if not hundreds of Gen0 collections before memory is reclaimed.

Ну.. то есть оно как бы и не обязательно, но желательно. Так?..
У меня WCF-сервис и сейчас нарисовалась проблема с освобождением памяти. Так что вот это вот освобождение тут как раз в тему. Но как? Я пока написал это в таком виде:

public DataTable Foo()
{
    DataTable dataTable = null;
    try
    {
        dataTable = GetFoo();
        return dataTable;
    }
    finally
    {
        dataTable.Dispose();
    }
}


Вроде ничего не падает, но я пока сам до конца не понимаю этого куска.. Dispose() тут отрабатывает, это понятно. Но что там происходит с возвращением объекта? Успевает ли WCF сериализовать и отдать его клиенту? Гарантированно ли это? Что бы тут такое покурить для просветления?

Плюс, смущает то, что код, я так понимаю, не поддающийся юнит-тестированию — в юниттесте я, наверное, получу объект, над которым только что произвели Dispose() и тест просто упадёт.

Я бегло порылся по интернету и нашёл какие-то упоминания атрибута AutoDispose, но просветления пока не пришло. На StackOverflow тоже какая-то чехарда — кто-то пишет, что нужно самому Dispose() вызывать, кто-то другой говорит, что WCF сам всё сделает, третьи советуют вообще не связываться с IDisposable-типами. Я и сам склоняюсь к последнему, но это на будущее. А пока нужно просто утечку ресурсов заткнуть.
С уважением, Artem Korneev.
Отредактировано 11.05.2017 7:21 Artem Korneev . Предыдущая версия .
Re[3]: WCF и IDisposable
От: JohnnyJ Германия  
Дата: 11.05.17 13:28
Оценка: 30 (4) +1
Здравствуйте, Artem Korneev, Вы писали:

AK>Здравствуйте, Sinix, Вы писали:


AK>>>Наткнулся тут на один метод в WCF-сервисе, который возвращает DataTable, а это Disposable тип.

S>>Ниччего страшного.
AK>[...]
S>>MarshalByValueComponent calls GC.SuppressFinalize(this) in its Dispose() — skipping this means having to wait for dozens if not hundreds of Gen0 collections before memory is reclaimed.

AK>Ну.. то есть оно как бы и не обязательно, но желательно. Так?..

AK>У меня WCF-сервис и сейчас нарисовалась проблема с освобождением памяти. Так что вот это вот освобождение тут как раз в тему. Но как? Я пока написал это в таком виде:

AK>
AK>public DataTable Foo()
AK>{
AK>    DataTable dataTable = null;
AK>    try
AK>    {
AK>        dataTable = GetFoo();
AK>        return dataTable;
AK>    }
AK>    finally
AK>    {
AK>        dataTable.Dispose();
AK>    }
AK>}
AK>


AK>Вроде ничего не падает, но я пока сам до конца не понимаю этого куска.. Dispose() тут отрабатывает, это понятно. Но что там происходит с возвращением объекта? Успевает ли WCF сериализовать и отдать его клиенту? Гарантированно ли это? Что бы тут такое покурить для просветления?


AK>Плюс, смущает то, что код, я так понимаю, не поддающийся юнит-тестированию — в юниттесте я, наверное, получу объект, над которым только что произвели Dispose() и тест просто упадёт.


AK>Я бегло порылся по интернету и нашёл какие-то упоминания атрибута AutoDispose, но просветления пока не пришло. На StackOverflow тоже какая-то чехарда — кто-то пишет, что нужно самому Dispose() вызывать, кто-то другой говорит, что WCF сам всё сделает, третьи советуют вообще не связываться с IDisposable-типами. Я и сам склоняюсь к последнему, но это на будущее. А пока нужно просто утечку ресурсов заткнуть.


По умолчанию WCF автоматически вызывает Dispose для входных параметров и возвращаемого результата метода по окончании обработки.
Этим поведением можно управлять, применяя OperationBehaviorAttribute.AutoDisposeParameters.
Зри в корень!
Re[3]: WCF и IDisposable
От: Lexey Россия  
Дата: 12.05.17 14:48
Оценка: 4 (1) +1
Здравствуйте, Artem Korneev, Вы писали:

AK>Я пока написал это в таком виде:


Не надо так писать. Это возврат объекта, для которого уже вызван Dispose. Тут он проходит в свете того, что Dispose реально ничего не делает. Но сам подход совершенно некорректен.
"Будь достоин победы" (c) 8th Wizard's rule.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.