Có thể chia sẻ dữ liệu giữa các miền AppDomain mà không cần chi phí Marshalling. Nhưng nó là một cách khá hacky. Bạn có thể tạo một đối tượng dữ liệu nguồn được chia sẻ bởi tham chiếu giữa tất cả các miền AppDomain. Bằng cách này, bạn sẽ nhận được tất cả dữ liệu vào một đối tượng được chia sẻ mà không cần chi phí của Marshalling. Âm thanh quá dễ để trở thành sự thật?
Điều đầu tiên là biết cách chia sẻ dữ liệu giữa các miền AppDomain mà không cần Marshalling. Đối với điều này, bạn nhận được địa chỉ đối tượng của đối tượng nguồn dữ liệu của bạn thông qua Marshal.UnsafeAddrOfPinnedArrayElement. Sau đó, bạn chuyển IntPtr này cho tất cả các miền AppDomain quan tâm đến điều này. Trong mục tiêu AppDomain bạn cần phải cast IntPtr này trở lại một tham chiếu đối tượng có thể được thực hiện JIT :: CastAny được thực hiện nếu bạn trả về một đối tượng từ một phương thức và đẩy con trỏ của nó vào trong ngăn xếp.
Viola bạn đã chia sẻ một đối tượng dưới dạng con trỏ đơn giản giữa AppDomain và bạn nhận được InvalidCastExceptions. Vấn đề là bạn phải đặt cho tất cả AppOomains LoaderOptimization của bạn.MultiDomain để đảm bảo rằng assembly xác định kiểu dữ liệu chia sẻ được nạp như là kiểu trung gian AppDomain có cùng con trỏ Method Table giữa tất cả các AppDomains.
Bạn có thể tìm thấy một ứng dụng ví dụ thực hiện chính xác điều này như một phần của WMemoryProfiler. Xem liên kết này để biết thêm detailed explanation and download link vào mã mẫu.
Mã cơ bản là
[LoaderOptimization(LoaderOptimization.MultiDomain)]
static public void Main(string[] args)
{
// To load our assembly appdomain neutral we need to use MultiDomain on our hosting and child domain
// If not we would get different Method tables for the same types which would result in InvalidCastExceptions
// for the same type.
var other = AppDomain.CreateDomain("Test"+i.ToString(), AppDomain.CurrentDomain.Evidence, new AppDomainSetup
{
LoaderOptimization = LoaderOptimization.MultiDomain,
});
// Create gate object in other appdomain
DomainGate gate = (DomainGate)other.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(DomainGate).FullName);
// now lets create some data
CrossDomainData data = new CrossDomainData();
data.Input = Enumerable.Range(0, 10).ToList();
// process it in other AppDomain
DomainGate.Send(gate, data);
// Display result calculated in other AppDomain
Console.WriteLine("Calculation in other AppDomain got: {0}", data.Aggregate);
}
}
Nguồn
2012-07-26 08:15:29
Tôi chưa viết mã. Chỉ cần làm việc trên thiết kế. Bạn có thể cho tôi biết về bất kỳ bài viết nào giải thích việc chia sẻ dữ liệu bằng cách sử dụng phương pháp đầu tiên bạn đăng không? – ata
Marshaling bằng cách tham chiếu sẽ tuần tự hóa dữ liệu, quá, nhưng trong phần nhỏ. Mỗi cuộc gọi phương thức sẽ trả về một chút thông tin có hiệu quả tuần tự hóa một chút dữ liệu. Đây có lẽ là một ý tưởng hay nếu bạn chỉ yêu cầu một phần nhỏ dữ liệu. Nhưng nếu bạn phải xử lý (gần như) toàn bộ dữ liệu, nhận được nó từng chút một với nhiều cuộc gọi tên miền chéo sẽ không thể tin được so với việc tuần tự hóa và truyền dữ liệu cùng một lúc. –
Nếu bạn đi theo con đường này, đừng quên ghi đè phương thức InitializeLifetimeService; điều đó đã khiến tôi phát điên một vài ngày trước ("Object" ... "đã bị ngắt kết nối hoặc không tồn tại ở máy chủ.") –