2010-11-07 157 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

相关问题