在 .NET 中使用 WEB SERVICE 的CallBacks机制 (4)

来源:互联网 发布:网络协议内容 编辑:程序博客网 时间:2024/05/21 15:04
测试
WEB SERVICE Callbacks的概念和设计能使用下列位于http://localhost虚拟目录的三个子项目一起测试。测试的概要已经在上述段落中(Web Service Callback部分)说明。所有项目已经加入了跟踪断点,这样我们可以清楚的看到程序运行的过程(http://www.sysinternals.com/)。下面是它们的实现代码:
1. Web Service A
namespace WebServiceA
{
  public class ServiceA : System.Web.Services.WebService
  {
    public ServiceA()
    {
      //CODEGEN: This call is required by the ASP.NET Web Services Designer
      InitializeComponent();
      Trace.WriteLine(string.Format("[{0}]ServiceA.ctor", GetHashCode()));
    }
 
    #region Component Designer generated code
    private void InitializeComponent()
    {
    }
    #endregion
 
    protected override void Dispose( bool disposing )
    {
      Trace.WriteLine(string.Format("[{0}]ServiceA.Dispose", GetHashCode()));
    }
 
    [WebMethod]
    public string DoSomeWorkA(int count, string ticket)
    {
      Trace.WriteLine(string.Format("[{0}]ServiceA.DoSomeWorkA start...",
        GetHashCode()));
      int startTC = Environment.TickCount;
 
      // current state
      Global.state[ticket] = "The job has been started";
      string state = ticket;
   
      // location of the source/target web services -
      // (hard coded for test purpose only!)
      string myWsdlUrl = "http://localhost/WebServiceA/ServiceA.asmx?wsdl";
      string targetWsdlUrl = "http://localhost/WebServiceB/ServiceB.asmx?wsdl";
           
      // call the WebService B
      WebServiceAccessor wsa = new WebServiceAccessor(targetWsdlUrl);
      object esObj = wsa.CreateInstance("ServiceB");
      object retval = wsa.Invoke(esObj, "BeginDoSomeWorkB", count,
         myWsdlUrl, state, null, null);
 
      // Wait for the call to complete
      WebClientAsyncResult ar = retval as WebClientAsyncResult;
      ar.AsyncWaitHandle.WaitOne();
 
      // retrieve a result
      object result = wsa.Invoke(esObj, "EndDoSomeWorkB", ar);
      int durationTC = Environment.TickCount - startTC;
      Trace.WriteLine(string.Format("[{0}]ServiceA.DoSomeWorkA done in {1}ms",
         GetHashCode(), durationTC));
 
      //
      Global.state.Remove(ticket);
      return result.ToString();
    }
 
    [WebMethod]
    public bool CallbackServiceA(string sender, string xmlEventArg)
    {
      WebServiceEventArgs ea = (WebServiceEventArgs)xmlEventArg;
      string msg = string.Format(
             "[{0}]ServiceA.CallbackServiceA({1}, [{2},{3},{4}])",
             GetHashCode(), sender, ea.name, ea.state, ea.param);
 
      if(Global.state.ContainsKey(ea.state))
      {
        Global.state[ea.state] = string.Format("{0}, [{1},{2},{3}]",
             sender, ea.name, ea.state, ea.param);
        Trace.WriteLine(msg);
        return true;
      }
           
      return false;
    }
 
    [WebMethod]
    public string AbortWorkA(string ticket)
    {
      Trace.WriteLine(string.Format("[{0}]ServiceA.AbortWorkA",
           GetHashCode()));
 
      if(Global.state.ContainsKey(ticket))
      {
        Global.state.Remove(ticket);
        return string.Format("#{0} aborted.", ticket);
      }
           
      return string.Format("#{0} doesn't exist.", ticket);
    }
 
    [WebMethod]
    public string GetStatusWorkA(string ticket)
    {
      if(Global.state.ContainsKey(ticket))
      {
        return string.Format("#{0} status: {1}", ticket, Global.state[ticket]);
      }
           
      return string.Format("#{0} doesn't exist.", ticket);
    }
  }
}
全局类:
namespace WebServiceA
{
  public class Global : System.Web.HttpApplication
  {
    static public Hashtable state = null;
 
    protected void Application_Start(Object sender, EventArgs e)
    {
      state = Hashtable.Synchronized(new Hashtable());
      Trace.WriteLine(string.Format("[{0}]ServiceA.Application_Start",
         GetHashCode()));
    }
    // ...
    protected void Application_End(Object sender, EventArgs e)
    {
      state.Clear();
      Trace.WriteLine(string.Format("[{0}]ServiceA.Application_End",
         GetHashCode()));
    }
  }
}
请求和Callback Web Methods运行在不同的Session 中,这是状态为什么保存在可共享的资源类(如Hashtable)中的原因。每个客户端的请求有一个单独的票据凭证,它是WEB  SERVICE和全球站点之间的一把通信钥匙(cookie)
2. Web Service B
这个网络服务非常简单。 只有一个 Web Methods模拟一些工作。 程序运行期间,服务开始启用Callback Web Methods。工作以同步的方式在运行一些循环操作。每个循环调用WebService”A”的Callback Web Methods,基于它的返回值,程序可以自动停止。Service. 可以在session中保持状态。
 
namespace WebServiceB
{
  public class ServiceB : System.Web.Services.WebService
  {
    public ServiceB()
    {
      //CODEGEN: This call is required by the ASP.NET Web Services Designer
      InitializeComponent();
      Trace.WriteLine(string.Format("[{0}]ServiceB.ctor", GetHashCode()));
    }
 
    #region Component Designer generated code
    private void InitializeComponent()
    {
    }
    #endregion
 
    protected override void Dispose( bool disposing )
    {
    Trace.WriteLine(string.Format("[{0}]ServiceB.Dispose", GetHashCode()));
    }
 
    [WebMethod(EnableSession=true)]
    public string DoSomeWorkB(int count, string callbackWS, string stateWS)
    {
    Trace.WriteLine(string.Format("[{0}]ServiceB.DoSomeWorkB start...",
            GetHashCode()));
      int startTC = Environment.TickCount;
 
      // async call to the ServiceA.CallbackServiceA method   
      WebServiceAccessor wsa = new WebServiceAccessor(callbackWS);
      object esObj = wsa.CreateInstance("ServiceA");
 
      // prepare the callback arguments: sender, EventArgs
      string sender = GetType().FullName;
      WebServiceEventArgs ea = new WebServiceEventArgs();
      ea.name = "This is a callback";
      ea.state = stateWS;
 
      for(int ii = 0; ii < (count & 0xff); ii++) // max. count = 255
      {
        ea.param = ii;
        string xmlEventArgs = ea;
        object retval = wsa.Invoke(esObj, "BeginCallbackServiceA",
             sender, xmlEventArgs, null, null);
           
        // simulate some task
        Thread.Sleep(250);
 
        // Wait for the call to complete
        WebClientAsyncResult ar = retval as WebClientAsyncResult;
        ar.AsyncWaitHandle.WaitOne();
 
        // result
        object result = wsa.Invoke(esObj, "EndCallbackServiceA", ar);
        if((bool)result == false)
        {
          Trace.WriteLine(string.Format(
             "[{0}]ServiceB.DoSomeWorkB has been aborted", GetHashCode()));
          return string.Format("#{0} aborted during the progress of {1}.",
             stateWS, ii);
        }
      }
      //
      int durationTC = Environment.TickCount - startTC;
      Trace.WriteLine(string.Format("[{0}]ServiceB.DoSomeWorkB done in {1}ms",
                GetHashCode(), durationTC));
      return string.Format("#{0} done in {1}ms", stateWS, durationTC);
    }
  }
}
原创粉丝点击