WCF Restful 服务 - 实施异步操作

WCF Restful Service - Implement Asynchronous Operations

好的,我需要澄清和验证是否建议在服务器上实施异步以及如何实施。

首先,这里是我的服务的一些细节:

现在,考虑到以上内容,我读到使服务操作异步将有助于 I/O 操作(即长 运行 数据库、外部 Web 服务调用、pdf 生成等) .但是,我似乎无法就如何做到这一点达成良好的共识。

Stephen Clearly 似乎是一个知识渊博的人,但是他的一个博客说永远不要在 Web 服务上使用 Task.Run,我认为我必须在制作 [=44= 的方法上使用] 服务调用我自己的 WCF 服务以使其异步。 (来源:http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html)。他建议使用 Task.FromResult?我的结果 cannot/should 没有被缓存?

因此,当我的服务收到请求时,它显然会为该请求创建一个线程。并且由于每个请求都会进行一个或多个数据库调用,因此将有一个 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;
}

在服务中使用异步操作的全部意义在于在您正在等待某事时释放线程。如果您的服务代码只做同步工作,那么 Task.Run() 允许您释放当前线程,但最终只是转移对一个线程的持有,对另一个线程没有任何作用。然后,您只是增加了处理管理异步操作所需的额外工作的开销。除非您的操作调用的任何方法具有异步等效项,否则您最好保持原样。例如,是否有 MobileData.GetNoteAttachmentDataAsync 方法 returns 一个任务?如果有,请使您的方法异步并等待该方法的响应。