1、代码重复执行
一个简单的WCF调用过程
private readonly DBHelperClient dbHelperClient = new DBHelperClient() ;
void xx()
{
dbHelperClient.getxxAsync() ;
dbHelperClient.getxxCompleted += (ox, ex) =>
{
//dosomething;
}
}
表面看这个调用过程,没什么问题,但你犯了3个错误。
1)、WCF这个类不能直接这样初始化,因为最后发布到IIS的时候,有可能会有域名,或者其他虚拟目录,最后的地址
会和开发时不一致,最好的办法是这样
public static DBHelperClient dbhelper
{
get
{
System.Windows.Browser.HtmlDocument html = System.Windows.Browser.HtmlPage.Document;
string DBHelperUrl = html.DocumentUri.ToString().Substring(0,html.DocumentUri.ToString().IndexOf("SurveyWorkFlowTestPage.html"));
DBHelperUrl = DBHelperUrl + "DBHelper.svc";
DBHelperClient _dbhelper = new DBHelperClient("BasicHttpBinding_IDBHelper", DBHelperUrl);
return _dbhelper;
}
}
建立一个通用的生成WCF客户端类,这样,即使最后的地址有变化,都不会造成找不到WCF服务。其中的一些变量,请根据实际情况自行更改
2)、第二个错误是很容易被忽视掉的,因为他不会造成你程序出错,但会造成这个异步方法反复执行
因为比如xx()过程是某个按钮点击执行的,这样的话,按钮点击一次,就会加载一次异步完成的事件,点击多次后,就会调用多次异步过程,
会增加服务器压力,甚至造成程序错误,正确的做法是将该异步事件的赋值过程放置到窗体的InitializeComponent();后面,或者是类的构造
函数中。
3)、第三个问题,这个异步过程可能在整个程序中会反复执行,会在不同的窗体或者类中都会执行,因为这个事件是默认生成在Reference.cs
中,如果用一个全局的WCF客户端,该事件就会被添加多次,很容易造成程序错误,正确的做法是,在每一个窗体或每个类中创建一个全局的
WCF客户端,当一个窗体和一个类中,会调用同一个异步方法多次,就应该创建多个WCF客户端,才不会造成事件被多次加载。
2、提供一个小技巧
在WCF后台,比如写保存或删除方法的时候,需要将后台的错误暴露出来,当没有错误就返回一个数据集,遇到这种情况的时候可以参考下面
做法.
1) 、在WCF后台建立一个类
[DataContract]
public class CallException
{
public CallException() { }
public CallException(string detail)
{
Message = "系统错误";
Detail = detail;
}
[DataMember]
public string Message { get; set; }
[DataMember]
public string Detail { get; set; }
}
2)、在接口部分这样定义你的函数
[OperationContract]
[FaultContract(typeof(CallException))]
List<CaseInfo> InsertProjectInfo(ProjectInfo projectInfo, out CallException callException);
3)、实现部分
public List<WorkFlowDefine> InsertWFDefine(WFDefine wfDefine, out CallException callException)
{
var workflowdefines = OROP<WorkFlowDefine>.GetEnties("id='" + wfDefine.WorkFlowDefine.Id + "' or name='" + wfefine.WorkFlowDefine.Name "'");
if (workflowdefines!=null)
{
callException = new CallException( "该业务类型编码或名称重复");
return null;
}
callException = null;
return string.IsNullOrEmpty(Err) ? OROP<WorkFlowDefine>.GetEnties() : null;
}
4)、客户端调用
Upublic.dbhelper.InsertWFDefineCompleted += (ox, ex) =>
{
if (ex.callException != null)
{
MessageBox.Show("保存失败,失败原因:" + ex.callException.Detail);
return;
}
_mDataGrid.ItemsSource = ex.Result;
_mDataPager.Source = ex.Result;
DialogResult = true;
};
这样就可以处理WCF错误了。
文笔比较糟糕,希望大家对大家有用。