2010-04-04 25 views
7

Tôi vừa phát hiện ra rằng tải chậm trong Khuôn khổ thực thể chỉ hoạt động từ chuỗi tạo ra ObjectContext. Để minh họa cho vấn đề này, tôi đã làm một bài kiểm tra đơn giản, với một mô hình đơn giản chỉ chứa 2 thực thể: PersonAddress. Dưới đây là các mã:Tải xuống khuôn khổ thực thể không hoạt động từ chủ đề khác

private static void TestSingleThread() 
    { 
     using (var context = new TestDBContext()) 
     { 
      foreach (var p in context.Person) 
      { 
       Console.WriteLine("{0} lives in {1}.", p.Name, p.Address.City); 
      } 
     } 
    } 

    private static void TestMultiThread() 
    { 
     using (var context = new TestDBContext()) 
     { 
      foreach (var p in context.Person) 
      { 
       Person p2 = p; // to avoid capturing the loop variable 
       ThreadPool.QueueUserWorkItem(
        arg => 
        { 
         Console.WriteLine("{0} lives in {1}.", p2.Name, p2.Address.City); 
        }); 
      } 
     } 
    } 

Phương pháp TestSingleThread hoạt động tốt, tài sản Address được lười biếng nạp. Nhưng trong TestMultiThread, tôi nhận được NullReferenceException trên p2.Address.City, vì p2.Address là không có.

Đó là lỗi? Đây có phải là cách nó phải làm việc? Nếu có, có tài liệu nào đề cập đến nó không? Tôi không thể tìm thấy bất kỳ nội dung nào về chủ đề này trên MSDN hoặc Google ...

Và quan trọng hơn, có cách giải quyết khác không? (Trừ gọi một cách rõ ràng LoadProperty từ các sợi nhân ...)

Bất kỳ trợ giúp sẽ rất cảm kích

PS: Tôi đang sử dụng VS2010, vì vậy nó là EF 4.0. Tôi không biết nếu nó giống nhau trong phiên bản trước của EF ...

+1

Tôi không chắc về động cơ của bạn, nhưng nhóm .NET nối mã khuyến khích viết bằng Tác vụ và Hành động thay vì sử dụng rõ ràng hồ bơi chuỗi. Có lẽ ai đó có thể cung cấp một trích dẫn tốt về điều đó? –

+0

Bạn có thể giải thích về việc sử dụng 'p2' một chút không? Tôi đoán nó không thay đổi gì cả? –

+0

@ jarrett: có lẽ, nhưng nó không phải là vấn đề ... vấn đề sẽ giống với Task, vì nó vẫn sử dụng các luồng. @ Henk: nó không hoạt động hoặc không có 'p2', nhưng dù sao thì cũng cần thiết, nếu không mỗi lambda sẽ đóng trên cùng một biến; xem bài viết này để biết chi tiết: http://blogs.msdn.com/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx –

Trả lời

7

Đây có phải là thiết kế không? Vâng; mọi cuộc gọi đến Tải, ẩn hoặc rõ ràng, cuối cùng sẽ đi qua các số ObjectContextObjectContext is documented to be not thread-safe.

Cách giải quyết có thể là tách thực thể khỏi ngữ cảnh đối tượng trong chuỗi công việc và đính kèm nó vào ngữ cảnh đối tượng trong chuỗi hiện tại.

+0

Cảm ơn câu trả lời của bạn. Thật không may, trong trường hợp của tôi tạo ra một bối cảnh đối tượng chắc chắn là quá mức cần thiết. Tôi đang cố gắng tải hình ảnh vào một ứng dụng WPF bằng cách sử dụng một ràng buộc async, và tôi thực sự không muốn tạo ra một bối cảnh mới cho mỗi hình ảnh (khoảng 150 hình ảnh hiện tại) –

+0

Tôi nghĩ rằng tại thời điểm này bạn có một câu hỏi WPF , không phải là một câu hỏi của EF. Các quy tắc của EF rất đơn giản. Làm thế nào để làm theo họ bằng cách sử dụng WPF là một vấn đề khác. –

+0

Vâng, tôi đang sử dụng nó trong WPF, nhưng nó không phải là một vấn đề WPF cụ thể. Và điều duy nhất về luồng trong tài liệu là thông tin "an toàn chủ đề" thông thường giống nhau đối với hầu hết tất cả các lớp. Nó nói * không được đảm bảo là luồng an toàn *, không * không thể được sử dụng bởi nhiều luồng *. Không phải là thread an toàn không có nghĩa là bạn không thể sử dụng đa luồng ở tất cả, nó chỉ có nghĩa là bạn phải xử lý đồng bộ hóa chính mình. –

Các vấn đề liên quan