C# WebService异步处理/异步调用详解
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();
}
{
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();
}
}
{
//数据访问层
//获取用户列表,这里方便演示直接创建一个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();
}
}
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();
}
}
/// 任务管理器
/// </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秒...
测试完成,结果显示:
版权声明:本文为开发框架文库发布内容,转载请附上原文出处连接
NewDoc C/S框架网