C# WebService异步处理/异步调用详解
作者:C/S框架网  发布日期:2011/06/12 19:03:26
C# WebService异步处理/异步调用详解

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内容.

贴图图片

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

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

类结构图1

贴图图片

类结构2
贴图图片

客户端建立测试环境,测试窗体
贴图图片

异步调用测试类

//测试类
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任务管理器类

/// <summary>
/// 任务管理器
/// </summary>
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;
   
   /// <summary>
   /// 构造器.参数说明 taskview:异步处理任务显示界面 taskName:任务名称
   /// </summary>
   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;
   }
   
   /// <summary>
   /// 创建任务数据表结构
   /// </summary>
   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秒后...
贴图图片

点击[调用WebService方法(异步处理)任务2]按钮,等待30秒...
贴图图片

测试完成,结果显示:

贴图图片



上一篇 下一篇