2010-11-07 24 views
6

tôi có bây giờ cái gì đó như thế này:Có thể tạo dịch vụ web đầy đủ trong C# không?

public class Service1 : System.Web.Services.WebService 
{ 
    [WebMethod] 
    public string Method1() 
    { 
     SomeObj so = SomeClass.GetSomeObj(); //this executes very long time, 50s and more 
     return so.Method1(); //this exetus in a moment 
    } 

    [WebMethod] 
    public string Method2() 
    { 
     SomeObj so = SomeClass.GetSomeObj(); //this executes very long time, 50s and more 
     return so.Method2(); //this exetus in a moment 
    } 

... 
} 

Có thể làm cho dịch vụ web statefull để tôi có thể tái sử dụng SomeObj so và chỉ cần gọi phương pháp trên cùng một đối tượng?

Vì vậy, khách hàng sẽ sử dụng dịch vụ này trước tiên sẽ gọi phương thức web sẽ tạo đối tượng so và trả lại một số ID. Và sau đó trong các cuộc gọi tiếp theo, dịch vụ web sẽ tái sử dụng cùng một đối tượng so dựa trên ID.

EDIT


Đây là mã thực tế của tôi:

[WebMethod] 
public List<ProcInfo> GetProcessList(string domain, string machineName) 
{ 
    string userName = "..."; 
    string password = "..."; 
    TaskManager tm = new TaskManager(userName, password, domain, machineName); 

    return tm.GetRunningProcesses(); 
} 

[WebMethod] 
public bool KillProcess(string domain, string machineName, string processName) 
{ 
    string userName = "..."; 
    string password = "..."; 
    (new TaskManager(userName, password, domain, machineName);).KillProcess(processName);    
} 

Trả lời

6

dịch vụ web Stateful là không thể mở rộng và tôi không muốn giới thiệu họ. Thay vào đó, bạn có thể lưu trữ kết quả của các hoạt động tốn kém trong số cache. Bộ nhớ cache này có thể được phân phối thông qua các nhà cung cấp tùy chỉnh cho khả năng mở rộng tốt hơn:

[WebMethod] 
public string Method1() 
{ 
    SomeObj so = TryGetFromCacheOrStore<SomeObj>(() => SomeClass.GetSomeObj(), "so"); 
    return so.Method1(); //this exetus in a moment 
} 

[WebMethod] 
public string Method2() 
{ 
    SomeObj so = TryGetFromCacheOrStore<SomeObj>(() => SomeClass.GetSomeObj(), "so"); 
    return so.Method2(); //this exetus in a moment 
} 

private T TryGetFromCacheOrStore<T>(Func<T> action, string id) 
{ 
    var cache = Context.Cache; 
    T result = (T)cache[id]; 
    if (result == null) 
    { 
     result = action(); 
     cache[id] = result; 
    } 
    return result; 
} 
+0

Bạn có thể lưu trữ tất cả đối tượng trong bộ nhớ cache hoặc có bất kỳ hạn chế? Các đối tượng của tôi bao gồm các kết nối WMI mở tới các máy tính khác nhau. – Primoz

+0

Theo mặc định bộ nhớ cache được lưu trữ trong bộ nhớ và nếu bạn bắt đầu chạy trên bộ nhớ thấp, bộ nhớ sẽ tự động bị xóa. Vì vậy, có, bạn có thể lưu trữ nhiều như bạn muốn nhưng bạn nên luôn luôn kiểm tra xem đối tượng có trong bộ nhớ cache và không bao giờ dựa vào nó đang ở đó bởi vì bạn đã lưu trữ nó. –

+0

@ Dimitrov, bạn nên làm cho giải pháp của bạn loại an toàn bằng cách sử dụng một khóa. Trong khi một yêu cầu đang thực thi "result = action();" dòng, cần có thời gian, bất kỳ yêu cầu nào khác cũng sẽ thấy bộ nhớ cache là rỗng và lặp lại cùng một "result = action();" hàng. Xem http://en.wikipedia.org/wiki/Double-checked_locking – Sklivvz

0

Thay đổi ServiceContract của giao diện của bạn thành:

[ServiceContract(SessionMode = SessionMode.Required)] 

Và đặt thuộc tính sau vào lớp học của bạn:

[ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode.PerSession)] 

Xem http://msdn.microsoft.com/en-us/library/system.servicemodel.sessionmode.aspx để biết thêm thông tin và ví dụ.

1

Lựa chọn 1

Bạn có thể sử dụng HttpSession của bạn.

//this executes very long time, 50s and more, but only once. 
private SomeObj SessionSomeObj { 
    get 
    { 
    var ret = (SomeObj)Session["SomeObjStore"] ?? SomeClass.GetSomeObj(); 
    SessionSomeObj = ret; 
    return ret; 
    } 
    set { Session["SomeObjStore"] = value; } 
} 

[WebMethod(EnableSession = true)] 
public string Method1() 
{ 
    return SessionSomeObj.Method1(); //this exetus in a moment 
} 

[WebMethod(EnableSession = true)] 
public string Method2() 
{ 
    return SessionSomeObj.Method2(); //this exetus in a moment 
} 

Lưu ý rằng điều này sẽ chỉ hoạt động nếu một cuộc gọi cho mỗi khách hàng được thực hiện tại một thời điểm.

Lựa chọn 2

Bạn có thể rời khỏi lớp như được nhưng sử dụng WebMethod khác nhau. Nếu bạn đang gọi từ một lớp .Net được tạo, các phương thức async được cung cấp cho những lần xuất hiện này. Về cơ bản bạn gọi phương thức bắt đầu Method1 và nhận lại cuộc gọi khi thực hiện xong. Bạn có thể cần phải tinh chỉnh tham số timeout của lớp máy khách dịch vụ web để làm việc này.

Lựa chọn 3

Bạn có thể sử dụng caching features của SixPack library để làm điều này dễ dàng! ;-)


[Sửa sau khi bình luận]Hiện nay có hai lĩnh vực tĩnh trong phương án 1 để cho phép hai trường hợp khác nhau, mỗi phương pháp, theo yêu cầu.


[Sửa sau khi giải thích thêm]Sử dụng Session để làm cho các cuộc gọi stateful.

Xem: http://msdn.microsoft.com/en-us/library/aa480509.aspx

Cũng được thêm vào Tùy chọn 3.

+0

Tùy chọn 1 là không đi vì khách hàng khác nhau cần đối tượng "so" khác nhau để gọi phương thức. – Primoz

+0

Tôi nghĩ chúng ta có một số sai lầm. Client1 tạo đối tượng của đối tượng "so" và sau đó gọi phương thức1 đến phương thứcN trên cá thể này. Client2 tạo một thể hiện "oject" khác và một lần nữa gọi các phương thức giống nhau hoặc khác nhau trên cá thể này. Vì vậy, cần phải có khác nhau "như vậy" ví dụ cho mỗi khách hàng – Primoz

+0

Sau đó, bạn có thể sử dụng một từ điển thay vào đó ... Vấn đề chính với phương pháp này là các đối tượng không tồn tại vượt quá tuổi thọ của AppDomain. – CodesInChaos

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