2010-01-11 19 views
27

Vì vậy, đây là một đoạn trích từ một trong các lớp học của tôi:Làm thế nào một trường tĩnh chỉ đọc có thể là null?

[ThreadStatic] 
    readonly static private AccountManager _instance = new AccountManager(); 

    private AccountManager() 
    { 
    } 

    static public AccountManager Instance 
    { 
     get { return _instance; } 
    } 

Như bạn có thể thấy, đó là một chủ đề singleton-per-- ví dụ: trường hợp được đánh dấu bằng các thuộc tính ThreadStatic. Ví dụ này cũng được khởi tạo như là một phần của cấu trúc tĩnh.

Vì vậy, đó là trường hợp, làm thế nào là nó có thể là tôi nhận được một NullReferenceException trong ứng dụng ASP.NET MVC của tôi khi tôi cố gắng sử dụng tài sản Instance?

+1

chương trình mà bạn đang cố gắng sử dụng nó, mà có thể giúp đỡ, nơi nullref đang giảm sút – curtisk

+0

Nó đang được tiêu thụ trong ứng dụng ASP.NET từ một wrapper - công IAccount Nhận (string email) { trở lại lý Tài khoản .Instance.Nhận (email); } Điều này có thể phức tạp hơn tôi nghĩ; giết chết máy chủ web (máy chủ sẵn có trong VS) và khởi động lại ứng dụng đã làm cho sự cố biến mất ... – gerrod

Trả lời

38

Trích dẫn MSDN ThreadStaticAttribute:

Không chỉ định giá trị ban đầu cho Những ô có dấu ThreadStaticAttribute, bởi vì như vậy khởi chỉ xảy ra một lần, khi các nhà xây dựng lớp thực thi, và do đó chỉ ảnh hưởng đến một thread. Nếu bạn không chỉ định giá trị ban đầu, bạn có thể dựa vào trường là được khởi tạo thành giá trị mặc định nếu nó là loại giá trị hoặc tham chiếu null (Không có gì trong Visual Basic) nếu . kiểu.

+0

+1 để cung cấp tham chiếu –

+0

Đồng ý, tôi đã đánh dấu đây là câu trả lời. Cảm ơn Austin! – gerrod

1

Tôi tin rằng điều đang xảy ra là trường tĩnh chỉ được khởi tạo một lần vì vậy khi một luồng khác cố đọc trường, nó sẽ là rỗng (vì giá trị mặc định của nó) vì không thể khởi tạo lại _instance. Nó chỉ là một suy nghĩ nhưng tôi có thể hoàn toàn rời đi nhưng đó là những gì tôi nghĩ đang xảy ra.

12

Đây là một phần khó hiểu của thuộc tính ThreadStatic. Mặc dù nó tạo ra một giá trị cho mỗi luồng, mã initalization chỉ chạy trên một trong các luồng. Tất cả các chủ đề khác truy cập vào giá trị này sẽ nhận được mặc định cho loại đó thay vì kết quả của mã khởi tạo.

Thay vì khởi tạo giá trị, hãy bọc nó trong thuộc tính để khởi tạo cho bạn.

[ThreadStatic] 
readonly static private AccountManager _instance; 

private AccountManager() 
{ 
} 

static public AccountManager Instance 
{ 
    get 
    { 
    if (_instance == null) _instance = new AccountManager(); 
    return _instance; 
    } 
} 

Bởi vì giá trị _instance là duy nhất cho mỗi thread, không khóa là cần thiết trong bất động sản và nó có thể bị đối xử như bất kỳ giá trị uể oải khởi tạo khác.

+0

Cảm ơn Jared; giải pháp của tôi trông khá giống với giải pháp của bạn nhưng tôi không biết điều đó về ThreadStatic. Vì vậy, đánh lừa tôi! – gerrod

8

Bạn đã đạt số cổ điển [ThreadStatic] "101" tại đây.

Trình khởi chạy tĩnh sẽ chỉ kích hoạt một lần, mặc dù nó được đánh dấu là [ThreadStatic], vì vậy các chủ đề khác (ngoài việc đầu tiên) sẽ thấy điều này chưa được khởi tạo.

0

Trường tĩnh được đánh dấu bằng ThreadStaticAttribute không được chia sẻ giữa các luồng. Mỗi chuỗi thực hiện có một trường riêng biệt của trường, và đặt độc lập và nhận các giá trị cho trường đó. Nếu trường được truy cập trên một luồng khác, trường đó sẽ chứa một giá trị khác.

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