Không có AppDomains trong .NET Core! Tại sao?


86

Có lý do chính đáng nào khiến Microsoft chọn không hỗ trợ AppDomains trong .NET Core không?

AppDomains đặc biệt hữu ích khi xây dựng các ứng dụng máy chủ đang chạy lâu dài, nơi chúng tôi có thể muốn cập nhật các tập hợp được tải bởi máy chủ một cách duyên dáng mà không cần tắt máy chủ.

Nếu không có AppDomains, làm thế nào chúng ta sẽ thay thế các assembly của mình trong một quy trình máy chủ đang chạy lâu dài?

AppDomains cũng cung cấp cho chúng tôi một cách để cô lập các phần khác nhau của mã máy chủ. Giống như, một máy chủ websocket tùy chỉnh có thể có mã socket trong miền ứng dụng chính, trong khi các dịch vụ của chúng tôi chạy trong miền ứng dụng phụ.

Nếu không có AppDomains, trường hợp trên là không thể.

Tôi có thể thấy một lập luận có thể nói về việc sử dụng khái niệm Máy ảo của Đám mây để xử lý các thay đổi lắp ráp và không phải chịu chi phí của AppDomains. Nhưng đây có phải là những gì Microsoft nghĩ hay nói? hoặc họ có một lý do cụ thể và các lựa chọn thay thế cho các tình huống trên?


9
Nhưng .NET Core 5 không phải là .NET Framework. Đây không phải là phiên bản sắp tới của .NET CLR 4.6 mà là một thứ riêng biệt khác, đừng lo lắng, AppDomain ở đây để tồn tại.
Adriano Repetti

2
Tôi hiểu vậy, nhưng nếu Microsoft tuyên bố rằng .NET Core 5 sẽ là đa nền tảng (Windows / Linux / Unix), thì tôi tò mò về lý do tại sao họ muốn loại bỏ một tính năng cốt lõi như AppDomain.
Aditya Pasumarthi

3
Tôi đoán (nhưng đó chỉ là ý kiến ​​của tôi) chúng khó triển khai hơn theo cách đa nền tảng, chúng làm chậm nhiều thứ và thêm phức tạp. Không có quá nhiều người sử dụng chúng (ít nhất là hầu hết mọi người không làm điều đó trực tiếp). Nếu bạn không cần chúng, bạn có thể sử dụng .NET Core. Nếu bạn cần chúng ... đừng sử dụng nó (hãy nghĩ đến ReFS và NTFS). Đơn giản là .NET Core không phải là .NET tương lai (cho đến nay) mà là một dự án riêng biệt. Có thể là một bàn làm việc nhưng chắc chắn không phải là một con đường di chuyển hoặc thay thế 1: 1 (ít nhất là bây giờ).
Adriano Repetti

@AdrianoRepetti: Hãy xem xét thêm câu trả lời này như một câu trả lời, vì tôi nghĩ nó hữu ích như vậy.
Patrick Hofman

@PatrickHofman đó chỉ là ý kiến ​​của tôi (bình luận thứ 2), tôi có thể trả lời với tư cách wiki cộng đồng nhưng tôi giao nhiệm vụ này cho một người thông thạo tiếng Anh hơn!
Adriano Repetti

Câu trả lời:


50

Điểm của tập con .NETCore là giữ cho một bản cài đặt .NET nhỏ . Và dễ dàng chuyển cảng. Đó là lý do tại sao bạn có thể chạy ứng dụng Silverlight trên cả Windows và OSX mà không phải đợi lâu khi truy cập trang web. Tải xuống và cài đặt thời gian chạy và khung hoàn chỉnh mất một vài giây, cho hoặc mất.

Giữ cho nó nhỏ chắc chắn cần phải cắt giảm các tính năng. Remoting rất cao trong danh sách đó, nó khá đắt. Nếu không thì cũng bị ẩn, nhưng bạn có thể ví dụ như thấy rằng các đại biểu không còn có phương thức BeginInvoke () chức năng nữa. Điều này cũng đưa AppDomain vào danh sách bị loại bỏ, bạn không thể chạy mã trong miền ứng dụng mà không cần hỗ trợ. Vì vậy, điều này hoàn toàn là do thiết kế.


12
IMHO nó không liên quan gì đến kích thước, nhưng với thực tế là CoreCLR không có cách đặt tên mạnh, và do đó có một hệ thống hợp nhất mới và một cách mới để xem lắp ráp là gì, danh tính của nó và nơi nó được tải vào, nghĩa là tên miền ứng dụng dưới dạng vùng chứa không còn hữu ích nữa.
Frans Bouma

7
Hmm, không. Tất nhiên, việc giữ kích thước tải xuống 6,6 MB sẽ yêu cầu xóa nhiều hơn một tính năng.
Hans Passant

7
AppDomains có thể hữu ích trong .NET đầy đủ ngay cả khi bạn không sử dụng cách đặt tên mạnh. (Ví dụ: khả năng cung cấp cách ly lỗi của AppDomains không phụ thuộc vào việc đặt tên mạnh.) Vì vậy, việc loại bỏ cách đặt tên mạnh sẽ không phải là lý do để xóa AppDomains.
Ian Griffiths

5
Tôi bối rối. Mối quan hệ giữa .Net Core và Silverlight là gì?
svick

10
Các lập trình viên có xu hướng cho rằng .NETCore là mới. Microsoft đã làm rất ít để xóa bỏ quan niệm này, ít nhất là bằng cách thay đổi số phiên bản 5.0 thành 1.0. CoreCLR đã có từ rất lâu, bắt đầu được sử dụng như là thời gian chạy cho .NET Compact. Silverlight và thời gian chạy WinRT / UWP là những ứng dụng đáng chú ý cho nó trước khi chúng tạo nguồn mở cho nó. Phiên bản thời gian chạy tốt nhất để lựa chọn, trước đó đã được chuyển sang OSX và các bộ xử lý di động WinCE khác nhau.
Hans Passant

46

Cập nhật cho .NET Standard 2 và .NET Core 2

Trong .NET Standard 2 các AppDomainlớp trong đó. Tuy nhiên, nhiều phần của API đó sẽ sử PlatformNotSupportedExceptiondụng .NET Core.

Lý do chính mà nó vẫn ở đó là vì những thứ cơ bản như đăng ký một trình xử lý ngoại lệ chưa xử lý sẽ hoạt động.

Câu hỏi thường gặp về tiêu chuẩn .NET có giải thích sau:

AppDomain có phải là một phần của .NET Standard không?

Loại AppDomain là một phần của .NET Standard. Không phải tất cả các nền tảng đều sẽ hỗ trợ việc tạo miền ứng dụng mới, chẳng hạn như .NET Core sẽ không hỗ trợ, vì vậy phương pháp AppDomain.CreateDomain khi có sẵn trong .NET Standard có thể ném PlatformNotSupportedException.

Lý do chính mà chúng tôi tiết lộ loại này trong .NET Standard là do mức sử dụng khá cao và thường không liên quan đến việc tạo miền ứng dụng mới mà để tương tác với miền ứng dụng hiện tại, chẳng hạn như đăng ký trình xử lý ngoại lệ chưa xử lý hoặc yêu cầu thư mục cơ sở của ứng dụng .

Ngoài ra, câu trả lời hàng đầu và các câu trả lời khác cũng giải thích lý do tại sao phần lớn AppDomain vẫn bị cắt (ví dụ: ném một ngoại lệ không được hỗ trợ).


20

Miền ứng dụng

Tại sao nó bị ngừng sản xuất? AppDomains yêu cầu hỗ trợ thời gian chạy và thường khá đắt. Mặc dù vẫn được CoreCLR triển khai nhưng nó không khả dụng trong .NET Native và chúng tôi không có kế hoạch thêm khả năng này vào đó.

Tôi nên sử dụng gì để thay thế? AppDomains đã được sử dụng cho các mục đích khác nhau. Để cách ly mã, chúng tôi đề xuất các quy trình và / hoặc vùng chứa. Để tải động các hợp ngữ, chúng tôi đề xuất lớp AssemblyLoadContext mới.

Nguồn từ Blog MSDN


Một câu hỏi, ý bạn là For code isolation, we recommend processes and/or containers... Có một api vùng chứa nào có sẵn trong lõi .net không?
Ivandro Jao

@IvandroIsmael, chúng có nghĩa là "chia ứng dụng / mô-đun đơn lẻ của bạn thành các ứng dụng / mô-đun / quy trình / vùng chứa tương tác riêng biệt" (hầu hết có thể - thành microservices), tức là cấu trúc lại ứng dụng của bạn để không sử dụng AppDomains để cô lập mã
Burst

10

Tại một thời điểm, tôi nghe nói rằng các tổ hợp dỡ tải sẽ được kích hoạt mà không cần sử dụng tên miền. Tôi nghĩ rằng System.Runtime.Loader.AssemblyLoadContextloại System.Runtime.Loader.dll có liên quan đến tác phẩm này, nhưng tôi không thấy bất kỳ thứ gì ở đó cho phép dỡ bỏ.


5

Tôi đã nghe trong một cuộc họp cộng đồng hoặc một số cuộc nói chuyện về Microsoft rằng tính năng cô lập của AppDomains được xử lý tốt hơn bởi các quy trình (và thực sự là mô hình phổ biến trong các nền tảng khác) và việc dỡ bỏ thực sự được lên kế hoạch như một tính năng bình thường không liên quan đến AppDomains.


5

Bạn không cần AppDomains nữa, bây giờ bạn có LoadContexts:

public class CollectibleAssemblyLoadContext 
    : AssemblyLoadContext
{
    public CollectibleAssemblyLoadContext() : base(isCollectible: true)
    { }
 
    protected override Assembly Load(AssemblyName assemblyName)
    {
        return null;
    }
}

byte[] result = null; // Assembly Emit-result from roslyn
System.Runtime.Loader.AssemblyLoadContext context = new CollectibleAssemblyLoadContext();
System.IO.Stream ms = new System.IO.MemoryStream(result);
System.Reflection.Assembly assembly = context.LoadFromStream(ms);


System.Type programType = assembly.GetType("RsEval");
MyAbstractClass eval = (MyAbstractClass )System.Activator.CreateInstance(programType);
eval.LoadContext = context;
eval.Stream = ms;
// do something here with the dynamically created class "eval"

và sau đó bạn có thể nói

eval.LoadContext.Unload();
eval.Stream.Dispose();

Phần thưởng nếu bạn đưa nó vào giao diện IDisposable của lớp trừu tượng, sau đó bạn có thể sử dụng bằng cách sử dụng, nếu bạn muốn.

Lưu ý:
Điều này giả định một lớp trừu tượng cố định trong một assembly chung

public abstract class MyAbstractClass 
{

     public virtual void foo()
     {}
}

và một lớp được tạo thời gian chạy động (sử dụng Roslyn), tham chiếu đến lớp trừu tượng trong hợp ngữ chung, lớp này thực hiện ví dụ:

public class RsEval: MyAbstractClass 
{

     public override void foo()
     {}
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.