C# 多线程 09-使用异步 I/O 04-异步调用 WCF 服务
🏷️ 《C# 多线程》
TIP
示例代码需要添加对 System.ServiceModel
的引用。
示例代码
csharp
/// <summary>
/// 异步调用 WCF 服务
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
ServiceHost host = null;
try
{
// 创建一个的主机(服务类型为 HelloWorldService;承载服务的地址为 http://localhost:1234/HelloWorld)
host = new ServiceHost(typeof(HelloWorldService), new Uri(SERVICE_URL));
var metadata = host.Description.Behaviors.Find<ServiceMetadataBehavior>() ?? new ServiceMetadataBehavior();
// 允许通过 HTTPGET 获取元数据
// (即可以通过浏览器访问 http://localhost:1234/HelloWorld?wsdl 或 http://localhost:1234/HelloWorld?singleWsdl 获取 xml 格式的元数据)
metadata.HttpGetEnabled = true;
// 指定正在使用的 WS-Policy 规范的版本。
metadata.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(metadata);
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
var endpoint = host.AddServiceEndpoint(typeof(IHelloWorldService), new BasicHttpBinding(), SERVICE_URL);
host.Faulted += (sender, e) => Console.WriteLine("Error!");
// 开启主机
host.Open();
Console.WriteLine($"Greeting service is running and listening on: {endpoint.Address} ({endpoint.Binding.Name})");
var client = RunServiceClient();
client.GetAwaiter().GetResult();
Console.WriteLine("Press Enter to exit");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine($"Error in catch block: {ex}");
}
finally
{
if (null != host)
{
if (host.State == CommunicationState.Faulted)
{
host.Abort();
}
else
{
host.Close();
}
}
}
}
const string SERVICE_URL = "http://localhost:1234/HelloWorld";
/// <summary>
/// 模拟远程访问 WCF 服务
/// </summary>
/// <returns></returns>
static async Task RunServiceClient()
{
var endpoint = new EndpointAddress(SERVICE_URL);
// 创建服务通道
var channel = ChannelFactory<IHelloWorldServiceClient>.CreateChannel(new BasicHttpBinding(), endpoint);
// 通过通道异步访问 Greet 服务
var greeting = await channel.GreetAsync("Eugene");
Console.WriteLine(greeting);
}
/// <summary>
/// 服务端接口
/// </summary>
[ServiceContract(Namespace = "Packt", Name = "HelloWorldServiceContract")]
public interface IHelloWorldService
{
[OperationContract]
string Greet(string name);
}
/// <summary>
/// 客户端服务接口
/// </summary>
[ServiceContract(Namespace = "Packt", Name = "HelloWorldServiceContract")]
public interface IHelloWorldServiceClient
{
[OperationContract]
string Greet(string name);
[OperationContract]
Task<string> GreetAsync(string name);
}
/// <summary>
/// 服务端实现
/// </summary>
public class HelloWorldService : IHelloWorldService
{
public string Greet(string name)
{
return $"Greetings, {name}";
}
}
运行结果
注意
运行需要管理员权限(使用管理员权限打开 VS,或者使用管理员权限运行编译生成的 exe 文件)
txt
Greeting service is running and listening on: http://localhost:1234/HelloWorld (
BasicHttpBinding)
Greetings, Eugene
Press Enter to exit
HelloWorldService 服务页面
服务地址:http://localhost:1234/HelloWorld
已创建服务。
若要测试此服务,需要创建一个客户端,并将其用于调用该服务。可以使用下列语法,从命令行中使用 svcutil.exe 工具来进行此操作:
bash
svcutil.exe http://localhost:1234/HelloWorld?wsdl
您还可以访问作为单个文件的服务说明:
这将生成一个配置文件和一个包含客户端类的代码文件。请将这两个文件添加到客户端应用程序,并使用生成的客户端类来调用服务。例如:
C#
csharp
class Test
{
static void Main()
{
HelloWorldServiceContractClient client = new HelloWorldServiceContractClient();
// 使用 "client" 变量在服务上调用操作。
// 始终关闭客户端。
client.Close();
}
}
Visual Basic
vb
Class Test
Shared Sub Main()
Dim client As HelloWorldServiceContractClient = New HelloWorldServiceContractClient()
' 使用 "client" 变量在服务上调用操作。
' 始终关闭客户端。
client.Close()
End Sub
End Class