2011-01-28 40 views
10

Như DateTime không thể được khai báo là không ổn định, là quyền này ?:dễ bay hơi DateTime

 private DateTime _time; 
     public DateTime Time 
     { 
      get 
      { 
       Thread.MemoryBarrier(); 
       return _time; 
      } 
      set 
      { 
       _time = value; 
       Thread.MemoryBarrier(); 
      } 
     } 

Đó tài sản có thể được truy cập từ chủ đề khác nhau, vì vậy tôi muốn đảm bảo họ nhận được luôn là phiên bản mới nhất, mà không cần sử dụng tranh (Khóa).

EDIT:

  • Tôi có một bộ sưu tập các khó tạo ra các mục, mỗi người có một tài sản DateTime tên CreationTime, cho thấy khi mặt hàng này đã được tạo ra. Nó được khởi tạo thành DateTime.UtcNow.
  • Mỗi khi một mục được truy cập, thuộc tính đó được cập nhật thành DateTime.UtcNow.
  • Có một chuỗi, thực thi theo thời gian kịp thời trong bộ hẹn giờ có luồng để kiểm tra xem (DateTime.UtcNow + 1 hour)> item.CreationTime, nếu đúng nó sẽ xóa mục đó.

Tôi muốn đảm bảo rằng khi "chuỗi xóa" được đưa vào bộ sưu tập, tất cả các mục đều có "Thời gian truy cập cuối cùng" mới nhất trên đó, vì vậy tôi có thể tránh tạo lại mục đó chỉ vì bộ nhớ cache đã giữ giá trị cho một vài phần nghìn giây: D

Cảm ơn bạn trước.

+0

Không chắc chắn nếu những gì bạn đang cố gắng làm có ý nghĩa. Làm thế nào để bạn xác định phiên bản mới nhất? – CodesInChaos

+0

Tôi đã cập nhật bài đăng – vtortola

+1

Do bạn đang triển khai bộ nhớ cache loại bỏ các đối tượng không được sử dụng cũ hơn một khoảng thời gian cụ thể, tôi nghĩ giải pháp 'InterlockedExchange' là cách để đi đến đây. –

Trả lời

12

Chính xác.

Nhưng, bạn có tùy chọn khác. Lưu trữ thời gian dưới dạng số lượng đánh dấu Int64 và sử dụng InterlockedExchange để đặt. Sau đó, các chủ đề có thể tự tạo DateTime bằng cách sử dụng hàm tạo Int64, không cho bạn tranh chấp và không có khóa.

CHỈNH SỬA:

Vì bạn đã cung cấp thêm thông tin, bây giờ sẽ dễ dàng hơn để cung cấp ví dụ.

public class Cache 
{ 
    class CacheEntry 
    { 
     private Int64 m_Touched; 

     public CacheEntry() 
     { 
      Touch(); 
     } 

     public void Touch() 
     { 
      System.Threading.Interlocked.Exchange(ref m_Touched, DateTime.Now.Ticks); 
     } 

     public DateTime Touched 
     { 
      get 
      { 
       return new DateTime(Interlocked.Read(ref m_Touched)); 
      } 
     } 
    } // eo class CacheEntry 
} // eo class Cache 
+3

Tốt hơn nên sử dụng 'ToBinary' /' FromBinary' thay vì chỉ lưu trữ các dấu tick thô, để 'DateTimeKind' được giữ nguyên. (Mặc dù tôi cho rằng OP có lẽ chỉ nên sử dụng 'khóa' và một' DateTime' đơn giản hơn là cố gắng quá thông minh.) – LukeH

+2

Mặc dù có thể, cả hai đề xuất này đều giống như có thể có rất nhiều dự phòng chuyển đổi có liên quan. Điều đó, tất nhiên, phụ thuộc vào số lượng người tiêu dùng mà giá trị DateTime có. –

+2

@ Sensai76, có lẽ nhưng tôi nghi ngờ việc chuyển đổi sẽ là một chi phí rắc rối (mặc dù thật khó để nói mà không biết làm thế nào điều này được sử dụng bởi các chủ đề khác), và nói rằng, nó sẽ ít chi phí hơn một số loại Khóa. –

2

Điều này là không thể - bạn sẽ cần sử dụng lock hoặc lớp Monitor để đồng bộ hóa quyền truy cập vào trường này.

Điều này là do DateTime là một loại giá trị - một sturcture.

Từ MSDN - volatile (C# Reference):

Các từ khóa dễ bay hơi có thể được áp dụng cho lĩnh vực các loại sau:

  • loại tham khảo.
  • Loại con trỏ (trong ngữ cảnh không an toàn). Lưu ý rằng mặc dù con trỏ chính nó có thể dễ bay hơi, nhưng đối tượng mà nó trỏ tới không thể. Nói cách khác, bạn không thể khai báo một "con trỏ dễ bay hơi".
  • Các loại như sbyte, byte, short, ushort, int, uint, char, float và bool.
  • Loại enum với một trong các loại cơ sở sau: byte, sbyte, short, ushort, int hoặc uint.
  • Thông số loại chung được gọi là loại tham chiếu.
  • IntPtr và UIntPtr.

Như những người khác đã đề cập, bạn có thể sử dụng Ticks để theo dõi thời gian.

2

Mã của bạn không an toàn chỉ vì chuyển nhượng DateTime không được đảm bảo là nguyên tử. Nói chung, các phép gán số nguyên lên đến 32 bit là nguyên tử, nhưng 64 không cần phải là nguyên tử.

Bạn có thể sử dụng Interlocked.Exchange với các dấu tích của số DateTime vì có thể lưu trữ nguyên tử Int64.

Nhưng nếu bạn chuyển sang dấu tích, bạn cần biết rằng chỉ 62 bit được sử dụng cho các dấu tick và 2 bit cho loại đó. Vì vậy, bạn không bị mất loại.

Và ngay cả khi bạn làm cho getter và setter nguyên tử một threadsafe, tôi không chắc chắn nếu đó là đủ. Kể từ khi thời gian có thể thay đổi giữa thời gian mà getter của bạn trở lại và thời gian bạn thực sự làm việc với thời gian bạn nhận được. Vì vậy, thời gian của bạn luôn có thể lỗi thời.

+0

đây là ứng dụng x64 dành cho máy x64. nó có quan trọng không? Điểm tốt. – vtortola

+0

@vtortola theo điều này, 64 bit bài tập có thể là nguyên tử: _The CLI đảm bảo rằng đọc và viết các biến của các loại giá trị có kích thước (hoặc nhỏ hơn) của kích thước con trỏ tự nhiên của bộ xử lý là nguyên tử; nếu bạn đang chạy mã C# trên hệ điều hành 64 bit trong phiên bản 64 bit của CLR thì việc đọc và ghi 64 bit đôi và số nguyên dài cũng được đảm bảo là nguyên tử. Ngôn ngữ C# không đảm bảo rằng, nhưng thông số thời gian chạy thực hiện._ https://stackoverflow.com/a/11745471/67824 –

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