通過應用程序域邊界傳遞IEnumerable通常不是個好主意嗎?通過應用程序域邊界傳遞IEnumerable
我問,因爲用我目前對IEnumerable實現的理解,枚舉器不會被使用,直到集合被枚舉。當您穿越應用程序邊界時,特別是涉及多個進程時,這是否會導致跨邊界多次出行,返回的每個項目都會出現一次?如果是這樣的話,那麼在可能的情況下,如果可能的話,將這個集合整體返回,就性能而言,它會更可取嗎?
通過應用程序域邊界傳遞IEnumerable通常不是個好主意嗎?通過應用程序域邊界傳遞IEnumerable
我問,因爲用我目前對IEnumerable實現的理解,枚舉器不會被使用,直到集合被枚舉。當您穿越應用程序邊界時,特別是涉及多個進程時,這是否會導致跨邊界多次出行,返回的每個項目都會出現一次?如果是這樣的話,那麼在可能的情況下,如果可能的話,將這個集合整體返回,就性能而言,它會更可取嗎?
首先,它取決於如何枚舉的對象是:是繼承自MarshalByRef
還是它是可序列化的。在第二種情況下,將副本傳遞給另一個appdomain,然後類似於數組方法。另一方面,如果它繼承自MarshalByRef
,它幾乎取決於枚舉器如何訪問所有者實例。
所以,一般來說,如果您知道預期會發生什麼,那麼我認爲您應該只通過IEnumerable
與應用程序域相關聯。否則,您可能會收到意想不到的結果或性能不佳。
是的,這是一個壞主意。枚舉器幾乎總是保持對枚舉集合的引用。假設兩者都是可序列化的,那麼當您跨越邊界時,您還將序列化整個集合。儘管沒有往返。
是的。即使通過線程傳遞也是不安全的。你最好把它轉換成數組來傳遞。
重新「安全」 - 只要線程(或本例中的「AppDomain」)運行良好,不應該成爲問題;但我同意陣列... – 2010-01-09 20:17:51
其實,假設MarshalByRefObject
,它是每項旅行(加1);一個到MoveNext()
,和一個到Current
(每MoveNext()
返回true
)。加上一個GetEnumerator()
電話,並且可能是Dispose()
。因此,對於MarshalByRefObject
,否:不要這樣做;使用數組。
但是,如果它不是MarshalByRefObject
它更有趣。例如,ADO.NET數據服務在LINQ API(IQueryable<T> : IEnumerable<T>
)上公開數據,但是這需要在需要時構建特定查詢,執行一次往返並在客戶端迭代。
當然,你可能不應該使用遠程過任何真正的距離(WCF偏好等),所以也許第一個場景是不是一個巨大的問題 - 你不會有太多延遲 。另外,您將在實體上具有相同的延遲問題(如果MarshalByRefObject
)或序列化成本(如果不是)。
個人而言,在很少場合我用遠程(通常只允許DLL卸載),我有一個MarshalByRefObject
代表某種服務,以及序列化實體對象。也許對我來說,可以預見的是,我使用protobuf-net來最小化序列化成本。
我只是在思考這個問題,並得出了相同的結論。我試圖在一個會去掉另一個域的大型序列化對象之間找到一個平衡點,然後在整個域上傳遞一個linq查詢來執行,然後將子集序列化回去。這個問題似乎是你可以跨域傳遞一個linq查詢而沒有負面影響(如阻止一個域加載其他類型?)。對此有何想法? – JoeBrockhaus 2014-11-30 18:23:33
@Joe一個有趣的想法,也許:一個命名的內存映射文件。讓它通過兩個應用程序域打開,並使用單獨的進程內鉤子(每個應用程序域本地可枚舉的部分)。讓操作系統擔心發現底層數據。 – 2014-11-30 18:28:54
啊,我明白了。我必須考慮這樣做。 (我只是在考慮我們當前插件框架的可擴展性。) – JoeBrockhaus 2014-11-30 18:47:11
我應該澄清說我正在假設MBR。鑑於這個答案和其他答案,我想我會避免IEnumerable返回值,除非在特定情況下有一個好的論點。 – redman 2010-01-09 19:03:37