[.Net码农]C# WebService异步处理/异步调用详解

http://www.csframework.com/archive/5/arc-5-20110612-1593.htm



C# WebService异步处理/异步调用详解(附实例源代码)


有时WebService后台程序在运算复杂的数据时客户界面呈现等候状态, 在有些情况下客户不愿意等候也不关心运算何时结束。从设计角度来看至少可使用两种方法解决:1.多线程 2.Web方法异步调用

本文重心是WebService技术,所以讲解Web方法异步调用吧!

先看后台代码,Web方法定义,注意标明 [WebMethod]的方法.
代码相当简单,只定义了3个返回数据的方法.

public  class Service : System.Web.Services.WebService
{
    public Service()
   {
       // 
   }
   
    //建立一个自己的Web方法 
   [WebMethod]
    public  byte[] GetUserList()
   {
       //返回用户列表 
       return  new UserData().GetUserList();
   }
   
   [WebMethod]
    public  byte[] AnsyTest1()
   {
       //Web方法,从数据访问层获取计算过的数据 
       return  new UserData().AnsyProcess1();
   }
   
   [WebMethod]
    public  byte[] AnsyTest2()
   {
       //Web方法,从数据访问层获取计算过的数据 
       return  new UserData().AnsyProcess2();
   }
   

从UserData类获取数据

public  class UserData
{
    //数据访问层 
    //获取用户列表,这里方便演示直接创建一个DataTable.(您可以从SqlServer获取数据) 
    public  byte[] GetUserList()
   {
      DataSet ds =  new DataSet();
      DataTable dt =  new DataTable();
      dt.Columns.Add("UserName",  typeof( string));
      ds.Tables.Add(dt);
       this.AddRow(dt, "admini-系统管理员");
       this.AddRow(dt, "test-测试员");
      
       //将DataSet转换为byte数组,用于Http传输。 
       return ZipObject.CompressionDataSet(ds);
   }
   
    //返回网站列表 
    public  byte[] GetWebSite()
   {
      DataSet ds =  new DataSet();
      DataTable dt =  new DataTable();
      dt.Columns.Add("WebName",  typeof( string));
      ds.Tables.Add(dt);
       this.AddRow(dt, "C#易学网-www.vjsdn.com");
       this.AddRow(dt, "C#易学论坛-www.vjsdn.com");
      
       //将DataSet转换为byte数组,用于Http传输。 
       return ZipObject.CompressionDataSet(ds);
   }
   
    private  void AddRow(DataTable dt,  string value)
   {
       //增加一条记录 
      DataRow row = dt.NewRow();
      row[0] = value;
      dt.Rows.Add(row);
   }
   
    public  byte[] AnsyProcess1()
   {
       //假设这里执行一个复杂的运算,需要用时10秒以上 
      Thread.Sleep(10 * 1000); //等待10秒 
      
       //运算完成,返回一个数据集 
       return GetUserList();
   }
   
    public  byte[] AnsyProcess2()
   {
       //假设这里执行一个复杂的运算,需要用时30秒以上 
      Thread.Sleep(30 * 1000); //等待30秒 
      
       //运算完成,返回一个数据集 
       return GetWebSite();

  
   }
}


后台准备就绪,按F5运行,Service.asmx内容.

[.Net码农]C# WebService异步处理/异步调用详解_第1张图片

从上图看出Service.asmx暴露了3个Web方法. (从客户端调用这些方法)

客户端添加Web Refernces, 命名为UserWebService,引用完成后自动生成Service类.

类结构图1

[.Net码农]C# WebService异步处理/异步调用详解_第2张图片

类结构2
[.Net码农]C# WebService异步处理/异步调用详解_第3张图片

客户端建立测试环境,测试窗体
[.Net码农]C# WebService异步处理/异步调用详解_第4张图片

异步调用测试类

//测试类 
public  class WebServiceTester
{
    public  void Test1(DataGridView taskView, DataGridView resultView)
   {
       new TaskManager(taskView, resultView, "异步处理1进程").AsyncAnalysisAttendStep1();
   }
   
    public  void Test2(DataGridView view, DataGridView resultView)
   {
       new TaskManager(view, resultView, "异步处理2进程").AsyncAnalysisAttendStep2();
   }
}


TaskManager任务管理器类

///  
/// 任务管理器 
/// 
 
public  class TaskManager
{
    private  static  int TaskIDSequence = 0;  //所有任务序号 
   
    private Service _webService =  null;
    private DataTable _TaskData =  null//任务列表数据 
    private DataGridView _TaskView =  null; //任务列表表格显示 
    private DataGridView _ResultView =  null//显示运算结果 
    private  string _TaskName =  string.Empty;
    private  int _TaskID = 0;
   
    ///  
    /// 构造器.参数说明 taskview:异步处理任务显示界面 taskName:任务名称 
    /// 
 
    public TaskManager(DataGridView taskview, DataGridView resultView,  string taskName)
   {
       //增加任务序号 
      TaskManager.TaskIDSequence += 1;
      _TaskID = TaskManager.TaskIDSequence;
      _TaskView = taskview;
      _TaskName = taskName;
      _ResultView = resultView;
      _webService =  new Service();
      
       if (taskview.DataSource ==  null)
      {
         _TaskData = TaskManager.CreateTaskTable();
         taskview.DataSource = _TaskData;
      }
       else
      _TaskData = taskview.DataSource  as DataTable;
   }
   
    ///  
    /// 创建任务数据表结构 
    /// 
 
    public  static DataTable CreateTaskTable()
   {
      DataTable dt =  new DataTable();
      dt.Columns.Add("TaskID",  typeof( int));
      dt.Columns.Add("TaskName",  typeof( string));
      dt.Columns.Add("Content",  typeof( string));  //任务内容 
      dt.Columns.Add("FromTime",  typeof(DateTime)); //任务开始时间 
      dt.Columns.Add("ToTime",  typeof(DateTime)); //结束时间 
      dt.Columns.Add("Status",  typeof( string)); //处理状态 
      dt.Columns.Add("TimeUsed",  typeof( string));  //处理结束使用时间秒(s) 
       return dt;
   }
   
      //异步处理1 
    public  void AsyncAnalysisAttendStep1()
   {
      AddTask("异步处理1进程");
      _webService.AnsyTest1Async();  //调用AnsyTest1方法的异步方法.尾部是Async的方法。 
      _webService.AnsyTest1Completed +=  new AnsyTest1CompletedEventHandler(OnStep1Completed);
   }
   
    //异步处理2 
    public  void AsyncAnalysisAttendStep2()
   {
      AddTask("异步处理2进程");
      
       //调用AnsyTest2方法的异步方法.尾部是Async的方法。 
      _webService.AnsyTest2Async();
      
      _webService.AnsyTest2Completed +=  new AnsyTest2CompletedEventHandler(OnStep2Completed);
   }
   
    //异步处理1结束时触发的事件 
    void OnStep1Completed( object sender, AnsyTest1CompletedEventArgs e)
   {
      CallCompletedMethod(e.Result, e.Error);
   }
   
    //异步处理2结束时触发的事件 
    void OnStep2Completed( object sender, AnsyTest2CompletedEventArgs e)
   {
      CallCompletedMethod(e.Result, e.Error);
   }
   
    private  void CallCompletedMethod( byte[] result, Exception exception)
   {
       //异步处理完成,且处理成功 
       if (exception ==  null)
      {
          if (result !=  null) //异步处理返回的数据
         {
            DataSet ds = ZipObject.DecompressionDataSet(result);
            _ResultView.DataSource = ds.Tables[0];
         }
         UpdateTaskStatus("处理完成.");
          string msg = "任务编号:" + _TaskID.ToString() + " 名称:" + _TaskName + "\n处理完成!";
         MessageBox.Show(msg);
      }
       else
      {
         UpdateTaskStatus("发生错误.");
          string msg = "任务编号:" + _TaskID.ToString() + " 名称:" + _TaskName + "\n处理时发生错误!\n\n 错误摘要:\n";
         msg = msg + exception.Message;
         MessageBox.Show(msg);
      }
   }
   
    //更新处理状态 
    private  void UpdateTaskStatus( string status)
   {
      DataRow[] task = _TaskData.Select("TaskID=" + _TaskID.ToString());
       if (task !=  null && task.Length > 0)
      {
         DateTime from = DateTime.Parse(task[0]["FromTime"].ToString());
         TimeSpan span = DateTime.Now - from;
          int timeused = Convert.ToInt16(span.TotalSeconds);
         
         task[0]["Status"] = status;
         task[0]["ToTime"] = DateTime.Now;
         task[0]["TimeUsed"] = timeused.ToString() + "s";
         _TaskData.AcceptChanges();
         _TaskView.Refresh();
      }
   }
   
    //增加一个任务 
    private  void AddTask( string content)
   {
      DataRow row = _TaskData.NewRow();
      row["TaskID"] = _TaskID;
      row["TaskName"] = _TaskName;
      row["Content"] = content;
      row["FromTime"] = DateTime.Now;
      row["Status"] = "处理中...";
      _TaskData.Rows.Add(row);
      _TaskData.AcceptChanges();
      _TaskView.Refresh();
   }   
}


好了,运行客户端点击[调用WebService方法(异步处理)任务1]按钮,等待10秒后...
[.Net码农]C# WebService异步处理/异步调用详解_第5张图片

点击[调用WebService方法(异步处理)任务2]按钮,等待30秒...
[.Net码农]C# WebService异步处理/异步调用详解_第6张图片

测试完成,结果显示:

[.Net码农]C# WebService异步处理/异步调用详解_第7张图片



你可能感兴趣的:(.Net码农)