【发布时间】:2015-11-19 19:34:00
【问题描述】:
好的,我需要澄清和验证是否建议在服务器上实现异步以及如何实现。
首先,这里是我的服务的一些细节:
- 在装有 Server 2012 R2 的服务器上托管在 IIS 8.5 中。
- 使用 .NET 4.5,可以使用 4.6 或更高版本。这里没有限制。
- WCF Restful 服务。并发模式 = 每次调用。
- 客户端是一个移动应用程序,已经在等待对我的服务的每个服务操作调用。
- 实际上,每个方法都会调用数据库、另一个 Web 服务(不是异步 Web 服务)或生成 PDF。我是认真的。每一个。单身的。打电话。
- 希望使用基于任务的异步操作。
现在,考虑到上述内容,我读到使服务操作异步将有助于 I/O 操作(即长时间运行的数据库、外部 Web 服务调用、pdf 生成等)。但是,我似乎无法就如何做到这一点达成共识。
Stephen 显然是个知识渊博的人,但是他的一个博客说永远不要在 Web 服务上使用 Task.Run,我认为我必须在自己调用数据库/Web 服务的方法上使用它WCF 服务以使其异步。 (来源:http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html)。他建议使用 Task.FromResult?我的结果不能/不应该被缓存?
因此,当我的服务收到请求时,它显然会为该请求创建一个线程。而且由于实际上每个请求都会进行一个或多个数据库调用,因此会有一个 I/O 操作。我希望该线程去为另一个人的传入请求提供服务,而不是被该 I/O 操作所束缚,因此需要进行异步服务操作,并且一旦该数据库调用完成(I/O 操作),一个线程就会选择在原始请求停止的地方。我究竟如何在代码中实现这一点?
这是当前(显然)同步版本的代码示例。如上所述,我需要做什么才能使其异步?
我想我只是异步此服务操作并等待对 MobileData.GetNoteAttachmentData 的调用。在 GetNoteAttachmentData 中我需要做什么?
示例服务操作:
public NoteAttachmentContract GetNoteAttachmentData(string annotationId)
{
DataSet NoteAttachmentData = null;
MobileData MobileData = new MobileData();
NoteAttachmentContract Result = null;
TokenContract CurrentToken = MobileData.GetToken();
try
{
NoteAttachmentData = MobileData.GetNoteAttachmentData(CurrentToken, annotationId);
if (NoteAttachmentData != null && NoteAttachmentData.HasData())
{
DataRow NoteAttachmentRecord = NoteAttachmentData.Tables[0].Rows[0];
string DocumentBody = NoteAttachmentRecord["documentbody"].ToString();
string NoteId = NoteAttachmentRecord["annotationid"].ToString();
string FileName = NoteAttachmentRecord["filename"].ToString();
Result = new NoteAttachmentContract(DocumentBody, FileName, NoteId.IsGuid(false) ? new Guid(NoteId) : (Guid?)null);
}
}
catch (MobileServiceException ex)
{
throw ex;
}
catch (Exception ex)
{
throw new MobileServiceException(ex.Message, CurrentToken);
}
finally
{
if (NoteAttachmentData != null)
{
NoteAttachmentData.Dispose();
NoteAttachmentData = null;
}
}
return Result;
}
public DataSet GetNoteAttachmentData(TokenContract token, string annotationId)
{
DataSet Result = null;
SqlCommand Command = null;
try
{
using (SqlConnection connection = new SqlConnection(token.ConnectionString))
{
SqlParameter AnnotationIdParameter = new SqlParameter();
AnnotationIdParameter.SqlDbType = SqlDbType.UniqueIdentifier;
AnnotationIdParameter.ParameterName = "@AnnotationId";
AnnotationIdParameter.Value = new Guid(annotationId);
connection.Open();
Command = new SqlCommand(Properties.Resources.GetNoteAttachmentData, connection);
Command.Parameters.Add(AnnotationIdParameter);
using (SqlDataAdapter adapter = new SqlDataAdapter(Command))
{
adapter.Fill(Result);
Command.Parameters.Clear();
}
}
}
catch (Exception ex)
{
if (Result != null)
{
Result.Dispose();
Result = null;
}
throw ex;
}
finally
{
if (Command != null)
{
Command.Parameters.Clear();
Command.Dispose();
}
}
return Result;
}
【问题讨论】:
标签: c# web-services wcf asynchronous task