是否可以用 C# 创建有状态的 Web 服务?

发布于 2024-10-01 00:35:05 字数 1291 浏览 10 评论 0原文

我现在有这样的事情:

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

I have now something like this:

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 
    }

 ...
}

Is it possible to make stateful web service so that I can reuse SomeObj so and just call methods on the same object?

So the client which will use this service would first call web method which would create so object and return some ID.
And then in subsequent calls the web service would reuse the same so object based on ID.

EDIT


Here is my actual code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一花一树开 2024-10-08 00:35:05

有状态 Web 服务不可扩展,我不会推荐它们。相反,您可以将昂贵操作的结果存储在缓存中。该缓存可以通过自定义提供程序进行分发,以获得更好的可扩展性:

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

Stateful web services are not scalable and I wouldn't recommend them. Instead you could store the results of expensive operations in the cache. This cache could be distributed through custom providers for better scalability:

[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;
}
节枝 2024-10-08 00:35:05

选项 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 生成的类调用,则会为这些事件提供异步方法。基本上,您调用 Method1 开始请求方法并在执行完成时获得回调。您可能需要调整 Web 服务客户端类的超时参数才能使其正常工作。

选项 3

您可以使用缓存功能 SixPack 库 可以轻松完成此操作! ;-)


[在评论后编辑] 选项 1 中现在有两个静态字段,可根据要求允许两个不同的实例,每个方法一个。


[在评论后编辑进一步说明] 使用会话使调用有状态。

请参阅:http://msdn.microsoft.com/en-us/library/aa480509.aspx

还添加了选项 3。

Option 1

You can use your 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 
}

Note that this will only work if one call per client is made at a time.

Option 2

You can leave the class as is but use the WebMethod differently. If you are calling from a .Net generated class, async methods are provided for these occurrences. Basically you invoke the Method1 begin request method and get a call back when the execution is finished. You might need to tweak the timeout parameter of the web service client class for this to work though.

Option 3

You can use the caching features of the SixPack library to do this effortlessly! ;-)


[Edited after comment] There are now two static fields in option 1 to allow two different instances, one per method, as requested.


[Edited after further explanation] Using Session to make the calls stateful.

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

Also added Option 3.

戈亓 2024-10-08 00:35:05

将接口的 ServiceContract 更改为:

[ServiceContract(SessionMode = SessionMode.Required)]

并将以下属性放入您的类中:

[ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode.PerSession)]

请参阅 http://msdn.microsoft.com/en-us/library/system.servicemodel.sessionmode.aspx 了解更多信息和示例。

Change the ServiceContract of your interface into:

[ServiceContract(SessionMode = SessionMode.Required)]

And put the following attribute on your class:

[ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode.PerSession)]

See http://msdn.microsoft.com/en-us/library/system.servicemodel.sessionmode.aspx for more information and an example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文