2010-11-07 91 views
6

我現在是這樣的:是否可以在C#中創建有狀態的Web服務?

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 
    } 

... 
} 

是否有可能讓有狀態的web服務,這樣我可以重用SomeObj so並調用同一個對象的方法?

因此,將使用此服務的客戶端將首先調用web方法,該方法將創建so對象並返回一些ID。 然後在隨後的調用中,Web服務將根據ID重用相同的so對象。

編輯


這裏是我的實際代碼:

[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);    
} 

回答

6

狀態Web服務是不可擴展的,我不會推薦他們。相反,您可以將昂貴操作的結果存儲在cache中。此緩存可以通過自定義提供了更好的擴展性分佈:

[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

你可以存儲在緩存中的所有對象或有什麼限制嗎? 我的對象包含與各種計算機的打開WMI連接。 – Primoz 2010-11-07 13:10:48

+0

默認情況下,緩存存儲在內存中,如果您開始在低內存上運行,它將自動被驅逐。所以是的,你可以隨心所欲地存儲,但你應該經常檢查對象是否在緩存中,並且永遠不要因爲存儲它而依賴它。 – 2010-11-07 13:13:00

+0

@Darin Dimitrov,你應該通過使用鎖來使你的解決方案類型安全。當一個請求正在執行「result = action();」行,這需要時間,任何其他請求也會看到緩存爲空,並重復相同的「result = action();」線。見http://en.wikipedia.org/wiki/Double-checked_locking – Sklivvz 2010-11-07 13:22:25

1

選項1

您可以使用HttpSession中。

//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 
} 

需要注意的是,如果每個客戶一個電話在同一時間作出這樣纔有效。

選項2

可以保留類如但使用的WebMethod不同。如果您從.Net生成的類中調用,則會爲這些事件提供async方法。基本上,您可以調用Method1開始請求方法,並在執行完成時獲取回調。您可能需要調整Web服務客戶端類的超時參數才能使其工作。

選項3

您可以使用caching featuresSixPack library的毫不費力地做到這一點! ;-)


[註釋後編輯]現在有選項1中,以允許兩個不同的實例,每一個方法,如請求的兩個靜態字段。


[之後進一步解釋編輯]使用會話,使通話狀態。

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

還增加了選項3

+0

選項1不可用,因爲不同的客戶需要不同的「so」對象來調用方法。 – Primoz 2010-11-07 14:07:37

+0

我認爲我們有一些誤解。 Client1創建「so」對象的實例,然後在此實例上將method1調用到methodN。 Client2創建另一個「so」對象實例,並在此實例上再次調用相同或不同的方法。 因此,每個客戶端都需要有不同的「so」實例 – Primoz 2010-11-07 14:13:50

+0

然後您可以使用字典來代替......此方法的主要問題是對象不會超出AppDomain的生命週期。 – CodesInChaos 2010-11-07 14:18:36

相關問題