同步调用WCF服务的解决方案

在软件开发中,同步调用是一种常见的需求,尤其是在客户端与服务器之间的通信中。本文将介绍一种在Silverlight应用程序中实现同步调用WCF服务的方法。这种方法通过JavaScript和Silverlight的结合使用,解决了同步调用中常见的问题,如UI线程冻结等。

在阅读了CodeProject上Daniel Vaughan关于Silverlight同步调用的文章后,对他的实现方式持有不同意见。他的方法在异步线程中实现了同步调用,这在大多数同步问题中并不适用。在应用程序中,需要在Silverlight应用和LMS服务器(提供WCF服务)之间创建一个通信管道,因此需要一种更有效的同步调用方法。

解决方案

解决方案相对简单,使用了JavaScript,这是Silverlight的“血亲”,来帮助通过XmlHttpRequest对象调用WCF服务。创建了一个通用的JS函数,它将调用WCF前端的指定方法并添加指定的参数。

这个函数通过arguments数组读取由管理器传递的参数:

function SyncWCFServiceCaller() { var client = null; if (window.XMLHttpRequest) client = new XMLHttpRequest(); else if (window.ActiveXObject) client = new ActiveXObject("Microsoft.XMLHTTP"); var data = arguments[1]; client.open('POST', arguments[0], false); client.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); client.setRequestHeader('Content-Length', data.length + ''); client.send(data); var response = eval('(' + client.responseText + ')').d; return response; }

arguments[0]包含WCF端点和方法名称(例如 "localhost/service.svc/method")。arguments[1]包含序列化的参数(以JSON格式),如 {"name" : "daniel"}。这里没有复杂的内容。XmlHttpRequest创建了一个同步调用,所以如果它从Silverlight调用,它不会在服务返回之前返回调用者。

C#管理器也非常简单:

public class ContractToJavascriptCaller<T> { public string ServiceEndPointUri { get; private set; } public ContractToJavascriptCaller(string serviceEndPointUri) { this.ServiceEndPointUri = serviceEndPointUri; } public object CallMethod(string methodName, params string[] arguments) { StringBuilder builder = new StringBuilder(); builder.Append("{"); MethodInfo methodInfo = typeof(T).GetMethod(methodName); ParameterInfo[] parameters = methodInfo.GetParameters(); int parameterIndex = 0; foreach (ParameterInfo parameter in parameters) { builder.Append("\"").Append(parameter.Name).Append("\":\""); builder.Append(arguments[parameterIndex++]); builder.Append("\","); } string jsonSerializedParameters = builder.ToString().TrimEnd(','); jsonSerializedParameters = string.Concat(jsonSerializedParameters, "}"); return HtmlPage.Window.Invoke("SyncWCFServiceCaller", string.Concat(this.ServiceEndPointUri, "/", methodName), jsonSerializedParameters); } }

这个管理器只有一个方法CallMethod,它将使用服务端点和方法名称以及序列化为JSON的参数来调用JS函数。HtmlPage.Window.Invoke不会在WCF服务调用之前返回。

调用WCF服务

WCF服务包含两个方法:

string DoWork(string name); string DoWorkWithTwoParams(string name, string name2);

在它们的指令块中放入了一个Thread.Sleep指令,以模拟一组大的计算指令。WCF服务的接口在Silverlight项目中链接。所以调用WCF方法,只需要做:

ContractToJavascriptCaller<IDanielService> caller = new ContractToJavascriptCaller<IDanielService>("http://localhost:23770/DanielService.svc"); string response = caller.CallMethod("DoWork", this.firstMathodTextBlock.Text).ToString(); this.ResultTextBlock.Text = response;

对于UI线程冻结的问题,这种方法可以避免,因为它不会冻结浏览器。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485