WCF 中的基于任务的异步操作






4.84/5 (16投票s)
本文介绍了 WCF 的新功能“基于任务的异步操作”。
引言
虽然性能阻塞和迟缓是任何应用程序的绊脚石,但我们可以通过使用异步编程轻松克服这些瓶颈。但传统的异步编程方式编写、调试和维护并不容易。那么当今的解决方案是什么呢?
在我看来,这是基于任务的异步编程,它通过使用关键字await
和async
在 .NET 4.5 中得到更新。但是async
和await
的作用是什么?async
和await
是控制延续的方式。当一个方法使用async
关键字时,这意味着它是一个异步方法,其中可能包含一个await
关键字,如果它包含一个await
关键字,async
将激活它。因此,简单地说,async
激活了await
,从那时起,异步操作就开始了。这里有一个很好的解释。
在 WCF 中,我们也可以考虑在服务操作创建延迟调用时进行异步操作。有三种实现异步操作的方法:
- 基于任务的异步
- 基于事件的异步
IAsyncResult
异步
在本文中,我将使用基于任务的异步操作,因为这是最现代化的策略。
好的,让我们进入代码。
定义和实现服务
一个非常简单的服务契约,例如:
[ServiceContract]
public interface IMessage
{
[OperationContract]
Task<string> GetMessages(string msg);
}
有了这个简单的契约,实现起来就非常直接了。
public class MessageService : IMessage
{
async Task<string> IMessage.GetMessages(string msg)
{
var task = Task.Factory.StartNew(() =>
{
Thread.Sleep(10000);
return "Return from Server : " + msg;
});
return await task.ConfigureAwait(false);
}
}
这里,该方法使用async
关键字标记,这意味着它可能在内部使用await
关键字。这也意味着该方法能够在await
点暂停然后异步恢复。此外,它指示编译器将方法的输出或可能发生的任何异常提升到返回类型中。
服务托管
class Program
{
static void Main(string[] args)
{
var svcHost = new ServiceHost(typeof (MessageService));
Console.WriteLine("Available Endpoints :\n");
svcHost.Description.Endpoints.ToList().ForEach
(endpoints=> Console.WriteLine(endpoints.Address.ToString()));
svcHost.Open();
Console.ReadLine();
}
}
服务配置
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="Rashim.RND.WCF.Asynchronous.ServiceImplementation.MessageService">
<host>
<baseAddresses>
<add baseAddress="net.Tcp://:8732/"/>
<add baseAddress="https://:8889/"/>
</baseAddresses>
</host>
<endpoint address="Tcp" binding="netTcpBinding"
contract="Rashim.RND.WCF.Asynchronous.Services.IMessage"/>
<endpoint address="Http" binding="basicHttpBinding"
contract="Rashim.RND.WCF.Asynchronous.Services.IMessage">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<startup><supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5"/></startup>
</configuration>
配置服务后,我们需要配置客户端应用程序来使用该服务。
定义客户端
一个简单的控制台应用程序(客户端)
class Program
{
static void Main(string[] args)
{
GetResult();
Console.ReadLine();
}
private async static void GetResult()
{
var client = new Proxy("BasicHttpBinding_IMessage");
var task = Task.Factory.StartNew(() => client.GetMessages("Hello"));
var str = await task;
str.ContinueWith(e =>
{
if (e.IsCompleted)
{
Console.WriteLine(str.Result);
}
});
Console.WriteLine("Waiting for the result");
}
}
客户端配置
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMessage" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://:8889/Http" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IMessage"
contract="Rashim.RND.WCF.Asynchronous.Services.IMessage"
name="BasicHttpBinding_IMessage" />
</client>
</system.serviceModel>
</configuration>
最后,以下是proxy
类,客户端将通过它来使用服务。
public class Proxy : ClientBase<IMessage>, IMessage
{
public Proxy()
{
}
public Proxy(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public Task<string> GetMessages(string msg)
{
return Channel.GetMessages(msg);
}
}
就这样。虽然这很简单。