Передача IEnumerable через границы домена приложения


Является ли вообще плохой идеей передавать IEnumerable через границы домена приложения?

Я спрашиваю, потому что с моим нынешним пониманием реализаций IEnumerable перечислитель не будет использоваться, пока коллекция не будет, ну, перечислена. Когда вы пересекаете границы домена приложения, особенно с участием нескольких процессов, не приведет ли это к многократным переходам через границу, по одному для каждого возвращаемого элемента? Если это так, то возврат коллекции в ее целостность, когда это возможно, например в массиве, была бы предпочтительнее с точки зрения производительности, не так ли?

4 4

4 ответа:

- первых, это зависит от того, насколько объект должны быть пронумерованы, является: не является ли наследует от MarshalByRef или если он является сериализуемым. Во втором случае копия передается в другой домен приложения, который затем напоминает подход массива. С другой стороны, если он наследуется от MarshalByRef, это в значительной степени зависит от того, как перечислитель обращается к экземпляру владельца.

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

На самом деле, предполагая MarshalByRefObject, это 2 поездки по элементу (плюс один); один к MoveNext() и один к Current (для каждого MoveNext(), который возвращает true). Плюс вызов GetEnumerator() и, вероятно, вызов Dispose(). Поэтому для MarshalByRefObject Нет: не делайте этого; используйте массив.

Однако, если это не так MarshalByRefObject это гораздо интереснее. Например, ADO.NET службы Data Services предоставляют данные в LINQ API (IQueryable<T> : IEnumerable<T>), но это работает путем построения определенного запроса, когда это необходимо, выполнения одного кругового обхода и повторения в обратном направлении. клиент.

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

Лично, в очень немногих случаях , когда я использую удаленное взаимодействие (обычно только для того, чтобы разрешить выгрузку dll), у меня есть MarshalByRefObject, чтобы представлять какой-то вид обслуживания и сериализуемых объектов сущностей. Возможно, довольно предсказуемо для меня, я использую protobuf-net, чтобы минимизировать стоимость сериализации.

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

Да. даже передавать его по нитям небезопасно. вам лучше преобразовать его в массив для передачи.