参考资料:http://www.javashuo.com/article/p-dunodtqq-bu.htmlhtml
一、首先明确一点,就是无论怎样,finally必定会执行,即便程序有异常,而且在catch中thorw 了 ,finally仍是会被执行。ios
二、当try和catch中有return时,finally仍然执行。程序员
三、finally是在return后面的表达式运算完以后执行的,在执行完return时 ,程序并无跳出,而是进入到finally中继续执行,web
若是在finally若是对返回值进行了从新赋值,分为两种状况:编程
(1)当返回值是值类型(包括string类型,虽然是引用类型,这是特殊的个例)时,返回的值不受影响,c#
就是在trycatch时,返回的值已经肯定了。数组
public static string[] TestYinYong()
{
string[] arr = { "one", "two" };
try
{
throw new Exception();
}
catch (Exception)
{
return arr;
}
finally
{
arr[1] = "three";
}
}
此时返回的值是:{ "one", "three" };浏览器
四、finally中不能有return语句,编译都没法经过,提示:控制不能离开finally子句主体服务器
MSDN的定义:网络
lock 关键字能够用来确保代码块完成运行,而不会被其余线程中断。这是经过在代码块运行期间为给定对象获取互斥锁来实现的。
先来看看执行过程,代码示例以下:
假设线程A先执行,线程B稍微慢一点。线程A执行到lock语句,判断obj是否已申请了互斥锁,判断依据是逐个与已存在的锁进行object.ReferenceEquals比较(此处未加证明),若是不存在,则申请一个 新的互斥锁,这时线程A进入lock里面了。
这时假设线程B启动了,而线程A还未执行完lock里面的代码。线程B执行到lock语句,检查到obj已经申请了互斥锁,因而等待;直到线程A执行完毕,释放互斥锁,线程B才能申请新的互斥锁并执行
lock里面的代码。
接下来讲一些该lock什么对象。
为何不能lock值类型,好比lock(1)呢?lock本质上Monitor.Enter,Monitor.Enter会使值类型装箱,
每次lock的是装箱后的对象。lock实际上是相似编译器的语法糖,所以编译器直接限制住不能lock值类型。
退一万步说,就算能编译器容许你lock(1),可是object.ReferenceEquals(1,1)始终返回false(由于
每次装箱后都是不一样对象),也就是说每次都会判断成未申请互斥锁,这样在同一时间,别的线程照样能
够访问里面的代码,达不到同步的效果。同理lock((object)1)也不行。
那么lock("xxx")字符串呢?MSDN上的原话是:
锁定字符串尤为危险,由于字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串
都只有一个实例,就是这同一个对象表示了全部运行的应用程序域的全部线程中的该文本。所以,只要在应用
程序进程中的任何位置处具备相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的全部实例。
一般,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,若是该实例能够被公开访问,
则 lock(this) 可能会有问题,由于不受控制的代码也可能会锁定该对象。这可能致使死锁,即两个或更多个线
程等待释放同一对象。出于一样的缘由,锁定公共数据类型(相比于对象)也可能致使问题。并且lock(this)
只对当前对象有效,若是多个对象之间就达不到同步的效果。
lock(typeof(Class))与锁定字符串同样,范围太广了。
某些系统类提供专门用于锁定的成员。例如,Array 类型提供 SyncRoot。许多集合类型也提供 SyncRoot。
而自定义类推荐用私有的只读静态对象,好比:
private static readonly object obj = new object();
为何要设置成只读的呢?这是由于若是在lock代码段中改变obj的值,其它线程就畅通无阻了,由于互斥锁的
对象变了,object.ReferenceEquals必然返回false。
参考资料:https://www.cnblogs.com/jintianhu/archive/2010/11/19/1881494.html
许多应用程序使用多个线程,但这些线程常常在休眠状态中耗费大量的时间来等待事件发生。其余线程可能进入休眠状态,而且仅按期被唤醒以轮询更改或更新状态信息,而后再次进入休眠状态。为了简 化对这些线程的管理,.NET框架为每个进程提供了一个线程池,使应用程序可以根据须要来有效地利用多个线程。一个线程监视排到线程池的若干个等待操做的状态。当一个等待操做完成时,线程池中 的一个辅助线程就会执行对应的回调函数。线程池中的线程由系统进行管理,程序员不须要费力于线程管理,能够集中精力处理应用程序任务。
线程池是一种多线程处理形式,处理过程当中将任务添加到队列,而后在建立线程后自动启动这些任务。线程池线程都是后台线程。每一个线程都使用默认堆栈大小,以默认的优先级运行,并处于多线程单元 中。若是某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另外一个辅助线程来使全部处理器保持繁忙。若是全部线程池线程都始终保持繁忙,但队列中包含挂起的工做,则线程池将在 一段时间以后建立另外一个辅助线程。但线程的数目永远不会超过最大值。超过最大值的其余线程能够排队,但它们要等到其余线程完成后才启动。
线程池特别适合于执行一些须要多个线程的任务。使用线程池可以优化这些任务的执行过程,从而提升吞吐量,它不只可以使系统针对此进程优化该执行过程,并且还可以使系统针对计算机上的其余进程 优化该执行过程。若是须要启动多个不一样的任务,而不想分别设置每一个线程的属性,则可使用线程池。
若是应用程序须要对线程进行特定的控制,则不适合使用线程池,须要建立并管理本身的线程。
在如下几种状况下,适合于使用线程池线程:
(1)不须要前台执行的线程。
(2)不须要在使用线程具备特定的优先级。
(3)线程的执行时间不易过长,不然会使线程阻塞。因为线程池具备最大线程数限制,所以大量阻塞的线程池线程可能会阻止任务启动。
(4)不须要将线程放入单线程单元。全部 ThreadPool 线程均不处于多线程单元中。
(5)不须要具备与线程关联的稳定标识,或使某一线程专用于某一任务。
在多线程的程序中,常常会出现两种状况:一种是在应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,而后才能给予响应,这通常使用ThreadPool(线程池)来解决;另外一种状况是 在线程平时都处于休眠状态,只是周期性地被唤醒,这通常使用Timer(定时器)来解决。下面对ThreadPool类进行详细说明。
ThreadPool类提供一个线程池,该线程池可用于发送工做项、处理异步 I/O、表明其余线程等待以及处理计时器。该类提供一个由系统维护的线程池(能够看做一个线程的容器),该容器须要Windows 2000以上系统支持,由于其中某些方法调用了只有高版本的Windows才有的API函数。
下面介绍一下该类所提供的方法,如表1所示。
方法 |
描述 |
BindHandle |
将操做系统句柄绑定到ThreadPool |
GetAvailableThreads |
检索由GetMaxThreads方法返回的最大线程池线程数和当前活动线程数之间的差值 |
GetMaxThreads |
检索能够同时处于活动状态的线程池请求的数目。全部大于此数目的请求将保持排队状态,直到线程池线程变为可用 |
GetMinThreads |
检索线程池在新请求预测中维护的空闲线程数 |
QueueUserWorkItem |
将方法排入队列以便执行。此方法在有线程池线程变得可用时执行 |
RegisterWaitForSingleObject |
注册正在等待WaitHandle的委托 |
SetMaxThreads |
设置能够同时处于活动状态的线程池的请求数目。全部大于此数目的请求将保持排队状态,直到线程池线程变为可用 |
SetMinThreads |
设置线程池在新请求预测中维护的空闲线程数 |
UnsafeQueueNativeOverlapped |
将重叠的 I/O 操做排队以便执行 |
UnsafeQueueUserWorkItem |
注册一个等待 WaitHandle 的委托 |
UnsafeRegisterWaitForSingleObject |
将指定的委托排队到线程池 |
经过以上方法,能够对线程池进行设置以及相应的操做,那么,咱们何时使用线程池呢?咱们在用Thread类调用线程时,一次只能使用一个线程来建立和删除线程,这种方式的创建和删除线程对CPU 的使用是很频繁的,为了节省CPU的负荷,可使用线程池对线程进行操做,为了使读者更深刻的了解Thread类与ThreadPool类的差异。
在如下状况下,应使用ThreadPool类:
ThreadPool类会在线程的托管池中重用已有的线程。使用完线程后,线程就会返回线程池,供之后使用。ThreadPool有25个可用的线程(每一个处理器)。
在使用线程池时,通常调用ThreadPool类的QueueUserWorkItem方法。
用户并不须要自已创建线程,只须要把要进行的操做写成函数,而后做为参数传递给ThreadPool类的QueueUserWorkItem方法就好了,传递的方法是依靠WaitCallback代理对象,而线程的创建、管理、运 行等工做都是由系统自动完成的,用户无须考虑那些复杂的细节问题。ThreadPool类的用法:首先程序建立了一个ManualResetEvent对象,该对象就像一个信号灯,能够利用它的信号来通知其它线程
1.在多线程中线程池能够减小咱们建立线程,并合理的复用线程池中的线程。由于在线程池中有线程的线程处于等待分配任务状态。
2.没必要管理和维护生存周期短暂的线程,不用在建立时为其分配资源,在其执行完任务以后释放资源。
3.线程池会根据当前系统特色对池内的线程进行优化处理。
咱们把任务交给线程池去完成后,没法控制线程的优先级,设置线程的一些名称等信息。[不过咱们能够在放入线程池以前加一层来完善这些工做]
1 int workerThreads, completionPortThreads; 2 3 ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads); 4 Console.WriteLine("线程池中辅助线程的最大数目:{0}.线程池中异步 I/O 线程的最大数目:{1}", workerThreads, completionPortThreads); 5 6 ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads); 7 Console.WriteLine("线程池根据须要建立的最少数量的辅助线程:{0}.线程池根据须要建立的最少数量的异步 I/O 线程:{1}", workerThreads, completionPortThreads); 8 9 //设置线程池默认参数 10 ThreadPool.SetMaxThreads(100, 100); 11 ThreadPool.SetMinThreads(2, 2); 12 13 ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads); 14 Console.WriteLine("线程池中辅助线程的最大数目:{0}.线程池中异步 I/O 线程的最大数目:{1}", workerThreads, completionPortThreads); 15 16 ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads); 17 Console.WriteLine("线程池根据须要建立的最少数量的辅助线程:{0}.线程池根据须要建立的最少数量的异步 I/O 线程:{1}", workerThreads, completionPortThreads); 18 19 ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads); 20 Console.WriteLine("可用辅助线程的数目:{0}.可用异步 I/O 线程的数目:{1}", workerThreads, completionPortThreads);
参考资料:http://www.javashuo.com/article/p-nfktvxku-ca.html
参考资料:http://www.javashuo.com/article/p-srrkwiew-bn.html
A、在这个应用程序的Global.asax文件中建立一个Application_Error过程去处理ASP.NET代码错误。
B、在这个应用程序的Web.config文件中建立一个applicationError节去处理ASP.NET代码错误。
C、在这个应用程序的Global.asax文件中建立一个CustomErrors事件去处理HTTP错误。
D、在这个应用程序的Web.config文件中建立一个CustomErrors节去处理HTTP错误。
E、在这个应用程序的每一页中添加一个Page指示符去处理ASP.NET 代码错误。
F、 在这个应用程序的每一页中添加一个Page指示符去处理ASP.NET HTTP错误。
答案:CD
一、jQuery 事件 - ready() 方法
当 DOM(文档对象模型) 已经加载,而且页面(包括图像)已经彻底呈现时,会发生 ready 事件。
因为该事件在文档就绪后发生,所以把全部其余的 jQuery 事件和函数置于该事件中是很是好的作法。正如上面的例子中那样。
ready() 函数规定当 ready 事件发生时执行的代码。
ready() 函数仅能用于当前文档,所以无需选择器。
容许使用如下三种语法:
$(document).ready(function)
$().ready(function)
$(function)
二、window.onload和$(document).ready(function(){})的区别
一、执行时间上的区别:window.onload必须等到页面内(包括图片的)全部元素加载到浏览器中后才能执行。而$(document).ready(function(){})是DOM结构加载完毕后就会执行。
二、编写个数不一样:window.onload不能同时写多个,若是有多个window.onload,则只有最后一个会执行,它会把前面的都覆盖掉。$(document).ready(function(){})则不一样,它能够编写多个,而且每个都会执行。
三、简写方法:window.onload没有简写的方法,$(document).ready(function(){})能够简写为$(function(){})。
另外:因为在$(document).ready()方法内注册的事件,只要DOM就绪就会被执行,所以可能此时元素的关联文件未下载完,例如与图片有关的HTML下载完毕,而且已经解析为DOM树了,但颇有可能图片还未加载完毕,因此例如图片的高度和宽度这样的属性此时不必定有效。
要解决这个问题,可使用JQuery中另外一个关于页面加载的方法---load()方法。load()方法会在元素的onload事件中绑定一个处理函数。若是处理函数绑定在元素上,则会在元素的内容加载完毕后触发。如:$(window).load(function(){})=====window.onload = function(){}...
三、$(function(){}) 和 $(document).ready(function(){})
这两个方法的效果都是同样的,都是在dom文档树加载完以后执行一个函数,
一、
1 public class A 2 { 3 public A() 4 { 5 Print(); 6 } 7 public virtual void Print() 8 { 9
10 } 11 } 12 public class B : A 13 { 14 int x = 25; 15 int y; 16 public B() 17 { 18 y = -1; 19
20 } 21 public override void Print() 22 { 23 x = x + y; 24 y = x + 1; 25 Console.WriteLine("x={0},y={1}", x, y); 26 } 27 }
当使用 B b = new B(),输出:25,26
当使用 B b = new B(),b.Print() 输出: 24,25
参考资料:https://www.cnblogs.com/lhws/articles/1827330.html
一、using 命名空间名字。
例如:
using System
二、using别名
using 别名 = 包括详细命名空间信息的具体的类型。
using aClass = NameSpace1.MyClass;
三、using语句
只要离开了这个代码段就自动调用这个类实例的Dispose
using (MemoryStream ms = new MemoryStream(arr)) { }
参考资料:http://www.cnblogs.com/yuilin/archive/2011/10/28/2227881.html
在C#中推荐使用throw;来抛出异常;throw ex;会将到如今为止的全部信息清空,认为你catch到的异常已经被处理了,只不过处理过程当中又抛出新的异常,从而找不到真正的错误源。
第一种(不推荐使用,惋惜不少人都一直这么用的,包括俺,嘻嘻),这样适用会吃掉原始异常点,重置堆栈中的异常起始点:
try { } catch (Exception ex) { throw ex; }
第二种,可追溯到原始异常点,不过编译器会警告,定义的ex未有使用:
try { } catch (Exception ex) { throw; }
第三种,不带异常参数的,这个同第二种其实同样,可捕获全部类型的异常,IDE不会告警:
try { } catch { throw; }
第四种:通过对异常从新包装,可是会保留原始异常点信息。推荐使用。
try { } catch (Exception ex) { throw new Exception("通过进一步包装的异常", ex); }
例子:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 ExceptionClass ec = new ExceptionClass(); 6
7 try
8 { 9 ec.ExceptionThrow1(); 10 } 11 catch (Exception ex) 12 { 13 Console.WriteLine(ex.ToString()); 14 } 15
16 Console.WriteLine("---------------------------------------------------------------------"); 17
18 try
19 { 20 ec.ExceptionThrow2(); 21 } 22 catch (Exception ex) 23 { 24 Console.WriteLine(ex.ToString()); 25 } 26
27 Console.WriteLine("---------------------------------------------------------------------"); 28
29 try
30 { 31 ec.ExceptionThrow3(); 32 } 33 catch (Exception ex) 34 { 35 Console.WriteLine(ex.ToString()); 36 } 37
38 Console.WriteLine("---------------------------------------------------------------------"); 39
40 try
41 { 42 ec.ExceptionThrow4(); 43 } 44 catch (Exception ex) 45 { 46 Console.WriteLine(ex.ToString()); 47 } 48
49 Console.WriteLine("---------------------------------------------------------------------"); 50
51 Console.ReadKey(); 52 Console.WriteLine("------------"); 53
54
55 } 56 } 57 /// <summary>
58 /// 该Class用来测试异常抛出时相关上下文栈的调用状况 59 /// </summary>
60 public class ExceptionClass 61 { 62 /// <summary>
63 /// 抛出异常方法 64 /// </summary>
65 public void ExceptionThrow1() 66 { 67 try
68 { 69 // 调用原始异常抛出方法来抛出异常
70 this.ExceptionMethod(); 71 } 72 catch (Exception ex) 73 { 74 throw ex; 75 } 76 } 77
78 /// <summary>
79 /// 抛出异常方法1 80 /// </summary>
81 public void ExceptionThrow2() 82 { 83 try
84 { 85 this.ExceptionMethod(); 86 } 87 catch (Exception ex) 88 { 89 throw; 90 } 91 } 92
93 /// <summary>
94 /// 抛出异常方法2 95 /// </summary>
96 public void ExceptionThrow3() 97 { 98 try
99 { 100 this.ExceptionMethod(); 101 } 102 catch
103 { 104 throw; 105 } 106 } 107
108 /// <summary>
109 /// 抛出异常方法3 110 /// </summary>
111 public void ExceptionThrow4() 112 { 113 try
114 { 115 this.ExceptionMethod(); 116 } 117 catch (Exception ex) 118 { 119 throw new Exception("通过进一步包装的异常", ex); 120 } 121 } 122
123 /// <summary>
124 /// 原始异常抛出方法 125 /// </summary>
126 private void ExceptionMethod() 127 { 128 throw new DivideByZeroException(); 129 } 130 }
运行结果:
从运行的结果能够看到,第一种用法已经吃掉了原始异常信息。而其它3种用法均可以追溯到原始异常,推荐使用第四种用法
参考资料:http://www.cnblogs.com/JerryTian/archive/2012/09/24/2699459.html
1、什么是Web Service
1. 什么是Web Service呢?从表面上看,WebService就是一个应用程序,它向外界暴露出一个可以经过Web进行调用的API。这就是说,你可以用编程的方法经过Web调用来实现某个功能的应用程序。从 深层次上看,Web Service是一种新的Web应用程序分支,它们是自包含、自描述、模块化的应用,能够在网络(一般为Web)中被描述、发布、查找以及经过Web来调用。
2.Web Service即是基于网络的、分布式的模块化组件,它执行特定的任务,遵照具体的技术规范,这些规范使得Web Service能与其余兼容的组件进行互操做。它可使用标准的互联网协议,像超文本传 输协议HTTP和XML,将功能体如今互联网和企业内部网上。WebService平台是一套标准,它定义了应用程序如何在Web上实现互操做性。你能够用你喜欢的任何语言,在你喜欢的任何平台上写Web Service。
3.WebService 为Internet 上的组件服务•经过网络提供,以URL 定位方法调用•以Internet技术为基础•未來的分散式应用程序
2、Web Service的标准
1. SOAP(Simple Object Access Protocol)
2. UDDI(UnviversalDescription ,Discovery,andIntegration) 统一描述发现和集成协议–公开的,或是企业本身的注册与查询
3. WSDL(Web Service Description Language)–WebService 描述语言
3、Web Service的标准
1. XMLWeb Service 经过标准的Web 协议向Web 用户提供有用的功能。多数状况下使用SOAP 协议。
2. XMLWeb Service 能够很是详细地说明其接口,这使用户可以建立客户端应用程序与它们进行通讯。这种说明一般包含在称为Web 服务说明语言(WSDL)文档的XML 文档中。
3. XMLWeb Service 已通过注册,以便潜在用户可以轻易地找到这些服务,这是经过通用发现、说明和集成(UDDI)来完成的。
4.XMLWeb Service 体系结构的主要优势之一是:容许在不一样平台上、以不一样语言编写的各类程序以基于标准的方式相互通讯。
5.咱们将XMLWeb Service 定义为:经过SOAP 在Web 上提供的软件服务,使用WSDL 文件进行说明,并经过UDDI 进行注册。
4、SOAP
•Soap 是XML Web Service 的通讯协议。
•SOAP 是一种规范,用来定义消息的XML 格式 。包含在一对SOAP 元素中的、结构正确的XML 段就是SOAP 消息。
•SOAP 规范的其余部分介绍如何将程序数据表示为XML,以及如何使用 SOAP 进行远程过程调用 (RPC)。这些可选的规范部分用于实现 RPC 形式的应用程序,其中客户端将发出一条 SOAP 消息(包含可调用函数,以及要传送到该函数的参数),而后服务器将返回包含函数执行结果的消息。目前,多数 SOAP 实现方案都支持 RPC 应用程序。SOAP 还支持文档形式的应用程序,在这类应用程序中,SOAP 消息只是 XML 文档的一个包装。文档形式的 SOAP 应用程序很是灵活,许多新的 XML Web Service 都利用这一特色来构建使用 RPC 难以实现的服务
5、SOAP
•SOAP 规范的最后一个可选部分定义了包含SOAP 消息 的 HTTP 消息的样式。此 HTTP 绑定很是重要,由于几乎全部当前的OS(以及许多之前的 OS)都支持HTTP. HTTP 绑定虽然是可选的,但几乎全部 SOAP 实现方案都支持HTTP 绑定,由于它是SOAP 的惟一标准协议。因为这一缘由,人们一般误认为 SOAP 必须使用 HTTP。其实,有些实现方案也支持 MSMQ、MQ 系列、SMTP 或 TCP/IP 传输,但因为 HTTP 很是广泛,几乎全部当前的XML Web Service 都使用它。因为 HTTP 是 Web的核心协议,所以大多数组织的网络基础结构都支持HTTP。
• 到目前为止,SOAP 最引人注目的特征是它能够在许多不一样的软件和硬件平台上实现。这意味着SOAP 可用于连接企业内部和外部的不一样系统。
• HTTP 的普及和SOAP 的简单性使您几乎能够从任何环境调用它们,所以成为XMLWeb Service 的理想基础。 SOAP 的用户并不直接编写SOAP 消息,而是使用SOAP 工具包来建立和分析SOAP 消息。这些工具包一般将函数调用从某种语言转换为SOAP 消息。
5、UDDI
•UDDI 目录条目是介绍所提供的业务和服务的XML 文件。UDDI 目录条目包括三个部分。
“白页”介绍提供服务的公司:名称、地址、联系方式等等;
“黄页”包括基于标准分类法的行业类别;
“绿页”详细介绍了访问服务的接口,以便用户可以编写应用程序以使用 Web 服务。
服务的定义是经过一个称为类型模型(或 tModel)的 UDDI文档来完成的。多数状况下,tModel包含一个WSDL 文件,用于说明访问 XMLWeb Service 的SOAP 接口,可是tModel很是灵活,能够说明几乎全部类型的服务。
•UDDI 目录还包含若干种方法,可用于搜索构建您的应用程序所需的服务。例如,您能够搜索特定地理位置的服务提供商或者搜索特定的业务类型。以后,UDDI目录将提供信息、联系方式、连接和技术数据,以便您肯定能知足须要的服务。
•UDDI 容许您查找提供所需的Web 服务的公司。若是您已经知道要与谁进行业务合做,但尚不了解它还能提供哪些服务,这时该如何处理呢?WS-Inspection规范(英文)容许您浏览特定服务器上提供的XML Web Service 的集合,从中查找所需的服务。
5、wsdl
•Web Service Description Language (WSDL):用来定义WebService交换的文件格式以及提供服务方式的说明文件
•WSDL 表示 Web服务说明语言,是一个 XML文档,用于说明一组 SOAP 消息以及如何交换这些消息。WSDL对于 SOAP 的做用就象TLD 对于Tiglib的做用。因为WSDL 是 XML 文档,所以很容易进行阅读和编辑;但大多数状况下,它由软件生成和使用。
•要查看 WSDL 的值,能够假设您要调用由您的一位业务伙伴提供的SOAP 方法。您能够要求对方提供一些 SOAP消息示例,而后编写您的应用程序以生成并使用与示例相似的消息。WSDL 经过明确的表示法指定请求消息必须包含的内容以及响应消息的样式。
•WSDL 文件用于说明消息格式的表示法以XML 架构标准为基础,这意味着它与编程语言无关,并且以标准为基础,所以适用于说明可从不一样平台、以不一样编程语言访问的XML Web Service 接口。除说明消息内容外,WSDL 还定义了服务的位置,以及使用什么通讯协议与服务进行通讯。WSDL 文件定义了编写使用 XML Web Service 的程序所需的所有内容。
•当前,许多 SOAP工具包都包括从现有程序接口生成 WSDL 文件的工具,但却几乎没有直接用于编写WSDL 的工具,并且 WSDL的工具支持也很不完整。但不久就会出现编写 WSDL 文件的工具,接着还会有生成代理和存根的工具(与 COMIDL 工具很类似),这些工具将成为多数SOAP 实现方案的一部分。到那时,WSDL将成为建立 XML Web Service 的 SOAP接口的首选方法。 •由W3C制定的标准