2013-03-05 25 views
10

Tôi đang làm việc trên một ứng dụng C# đa luồng đang tiêu thụ một dịch vụ web WCF. Kết nối với webservice sẽ có thời gian chờ cụ thể mà chúng tôi có thể xác định và sau đó nó sẽ đóng. Tôi đang tìm cách lưu trữ kết nối với dịch vụ web bằng cách sử dụng lớp singleton. Tôi cố gắng để có được các trường hợp như sau:Loài đơn lười biếng trong ứng dụng đa số C#

CLazySingleton ins = CLazySingleton.Instance; 
string connection = CLazySingleton.abc; 

Dưới đây là mã cho lớp singleton:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace LazySingleton 
{ 
    public class CLazySingleton 
    { 
     private static readonly Lazy<CLazySingleton> _instance 
      = new Lazy<CLazySingleton>(() => new CLazySingleton()); 
     private static readonly object ThreadLock = new object(); 
     public static string abc; 
     //I will use the service connection object in place of 'abc' in the application 
     //assume that 'abc' is storing the connection object  

     private CLazySingleton() 
     { } 

     public static CLazySingleton Instance 
     { 
      get 
      { 
       if (abc == null) 
       { 
        lock (ThreadLock) 
        { 
         //Make the connection 
         abc = "Connection stored in this variable"; 
         Console.WriteLine("Connection Made successfully"); 
         return _instance.Value; 
        }      
       } 
       else 
       { 
        return _instance.Value; 
       } 
      } 
     } 
    } 
} 

Câu hỏi của tôi là: 1. Sẽ mã này có thể chăm sóc nhiều chủ đề cố gắng để có được dụ cùng một lúc? Đây là mối quan tâm lớn nhất của tôi. 2. Tôi có thể có giải pháp tốt hơn cho việc này không? 3. Tôi có cần phải sử dụng 'khóa' ở đây hay sử dụng phương pháp Lazy để xử lý các đa luồng đang cố gắng lấy ví dụ?

Mọi trợ giúp sẽ được đánh giá cao.

Cảm ơn!

+1

Kiểm tra bài viết này của Jon Skeet. Nó làm tốt công việc thảo luận về mẫu Singleton. http://www.yoda.arachsys.com/csharp/singleton.html – juharr

+0

Tôi có một số nghi ngờ về cách tiếp cận của bạn. Tại sao bạn cần phải duy trì một Singleton cho kết nối? Có vấn đề gì nếu mỗi luồng có proxy/kết nối riêng của nó? Và vì đó là một dịch vụ web, tôi không thấy trước bất kỳ vấn đề gì nếu bạn tạo ra nhiều kết nối. --- Để hiểu rõ hơn loại đối tượng là 'kết nối' của bạn là gì? – thewpfguy

+0

bạn không cần khóa – Rafa

Trả lời

5

đơn giản sử dụng ThreadSafetyMode

Lazy<MergeSort> ty = new Lazy<MergeSort>(LazyThreadSafetyMode.ExecutionAndPublication); 
+6

Phương thức khởi tạo mặc định của Lazy sử dụng LazyThreadSafetyMode.ExecutionAndPublication, đó là luồng an toàn theo mặc định. – Phil

+0

Cảm ơn, tôi chắc chắn sẽ thử điều này. –

8

Theo tài liệu Lazy Initialization của Microsoft, dưới phần có tiêu đề "Chủ đề An toàn khởi":

Theo mặc định, Lazy đối tượng là thread-safe.

Với điều này trong tâm trí, lĩnh vực abc bạn không cần phải tĩnh. Khi bạn đang sử dụng một số Lazy<T> để khởi tạo singleton của mình, thật an toàn để khởi tạo kết nối của bạn trong hàm tạo CLazySingleton.

+0

Xin chào Richard, Cảm ơn bạn đã phản hồi. Bạn đã làm một điểm tốt. Ngay cả tôi cũng đang suy nghĩ như vậy. Nhưng câu hỏi của tôi là, nếu tôi viết logic để tạo kết nối trong hàm tạo, làm thế nào tôi có thể quản lý kịch bản mà kết nối bị hết hạn bởi chính nó sau khi hết thời gian quy định. Trong trường hợp đó, trường abc sẽ trở thành null và lớp singleton sẽ tiếp tục trả về giá trị đó là null chỉ vì hàm tạo sẽ không được gọi lại. Tôi hy vọng rằng tôi có thể cung cấp quan điểm của tôi. –

+0

Tôi nghĩ việc sử dụng Singleton không phải là mẫu phù hợp ở đây, thực ra bạn không cần quản lý kết nối theo cách này. Và, bạn có chắc chắn bạn đang gọi một dịch vụ web, bởi vì loại thời gian chờ bạn đề cập đến ở đây là gì? – thewpfguy

3

Mã này có thể quản lý nhiều chủ đề cố gắng tải dụ cùng một lúc không?

Trong trường hợp của bạn có thể là trường "abc" được khởi tạo hai lần. Hãy tưởng tượng tình hình, biến "abc" đó là null. Chuỗi đầu tiên sẽ nằm trong khối "khóa" trước khi gán giá trị. Chủ đề thứ hai sẽ đợi trước khi khóa. Vì vậy, thread đầu tiên sẽ khởi tạo "abc" và thread thứ hai sẽ reinitialize nó (kiểm tra của bạn cho null là bên ngoài khóa, đó là lý do). Nhưng có lẽ đây không phải là điều bạn nên sợ.

Tôi có thể có giải pháp tốt hơn cho điều này không?

Có thể. Hãy để tôi mô tả nó trong khối cuối cùng của câu trả lời này.

Tôi có cần phải sử dụng 'khóa' ở đây hoặc sử dụng phương pháp lười biếng để quản lý đa luồng khi cố gắng tải xuống bản sao?

Tạo thuộc tính Giá trị trong lớp Lười là chủ đề an toàn. Trong kịch bản của bạn, tôi sẽ sử dụng lợi thế của tài sản IsValueCreated của Lazy <> lớp. Bạn sẽ vẫn cần đối tượng ThreadLock.Chỉ cần một điều nữa là, khi bạn truy cập vào bất động sản giá trị gia tăng của Lazy <> lớp, tài sản IsValueCreated sẽ trở thành sự thật (đó là lừa ;-))

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace LazySingleton 
{ 
    public class CLazySingleton 
    { 
     private static readonly Lazy<CLazySingleton> _instance 
      = new Lazy<CLazySingleton>(() => new CLazySingleton()); 
     private static readonly object ThreadLock = new object(); 
     public static string abc; 
     //I will use the service connection object in place of 'abc' in the application 
     //assume that 'abc' is storing the connection object  

     private CLazySingleton() 
     { } 

     public static CLazySingleton Instance 
     { 
      get 
      { 
       if (_instance.IsValueCreated) 
       { 
        return _instance.Value; 
       } 
       lock (ThreadLock) 
       { 
        if (abc == null) 
        { 
         abc = "Connection stored in this variable"; 
         Console.WriteLine("Connection Made successfully"); 
        } 
       } 
       return _instance.Value; 
      } 
     } 
    } 
} 
Các vấn đề liên quan