假设我们在wcf服务,同步和异步一个上定义了两个操作契约。有两个样本:
public void SubscribeSingle(int userId)
{
var clientId = this.OperationContext.GetClientId();
var session = this.OperationContext.GetPollingDuplexSession();
if (string.IsNullOrEmpty(clientId) || session == null || userId == 0)
{
return;
}
this.InternalSubscribeSingle(userId, clientId, session.SessionId);
}
和
public IAsyncResult BeginUnsubscribeSingle(int userId, AsyncCallback callback, object state)
{
var clientId = this.OperationContext.GetClientId();
var session = this.OperationContext.GetPollingDuplexSession();
if (string.IsNullOrEmpty(clientId) || session == null)
{
return null;
}
var asyncResult = new VoidAsyncResult(callback, state);
Task.Factory.StartNew(() =>
{
try
{
this.InternalUnsubscribeSingle(userId, clientId);
asyncResult.SetAsCompleted(false);
}
catch (Exception ex)
{
asyncResult.SetAsCompleted(ex, false);
}
});
return asyncResult;
}
public void EndUnsubscribeSingle(IAsyncResult result)
{
var response = result as VoidAsyncResult;
if (response != null)
{
response.EndInvoke();
}
}
据我所知,WCF服务内部也有一个线程池,因此每个I / O操作可能在另一个线程上完成。以及使用Task.Factory.StartNew
启动新线程从性能的角度来看,同步和异步服务器调用之间是否有任何区别,如果数据库访问是通过EntityFramework进行的并且虽然阻塞了吗?
答案 0 :(得分:2)
这两个版本是相同的。但通常,异步版本可能比异步调用同步版本更有效。
例如,如果我们使用FileStream或TcpListerner,那么调用BeginRead和BeginAcceptSocket的异步版本比调用Read和AcceptSocket等适当的同步版本要高效得多。那是因为那些异步函数使用操作系统提供的底层异步API。
例如,TcpListener可以使用IO完成端口与另一个tcp客户端进行交互,通过这种方法,您可以轻松地与10K客户端进行异步交互而不会出现延迟。 FileSteam可以使用Overlapped结构进行基础异步操作,这些操作比同步版本消耗更少的资源。
因此,如果您的服务异步方法也可以使用一些异步底层API,那么异步版本可能比在不同线程中调用同步版本的简单异步版本更有效。
答案 1 :(得分:1)
这里的异步方法没有任何价值,因为你仍然在调用一个会在某个时刻阻塞线程的同步方法。异步只会在一直到磁盘/网络IO之类的非阻塞操作时获得收益。只需编写简单的同步版本,让WCF做其事。