首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步Task<HttpResponseMessage> Get与HttpResponseMessage Get

异步Task<HttpResponseMessage> Get与HttpResponseMessage Get
EN

Stack Overflow用户
提问于 2014-09-18 08:11:15
回答 3查看 34.6K关注 0票数 10

我需要你在以下方面的帮助。近一个月来,我一直在阅读有关任务和异步的内容。

我想尝试在一个简单的wep api项目中实现我学到的新知识。我有以下两种方法,它们都能按预期工作:

代码语言:javascript
复制
 public HttpResponseMessage Get()
 {
        var data = _userServices.GetUsers();
        return Request.CreateResponse(HttpStatusCode.OK, data);
 }

public async Task<HttpResponseMessage> Get()
{
        var data = _userServices.GetUsers();


        return await Task<HttpResponseMessage>.Factory.StartNew(() =>
        {
           return Request.CreateResponse(HttpStatusCode.OK, data);
        });
 }

所以问题是。我试过使用fiddler,看看这两个有什么不同。异步的要快一点,但除此之外,在web api中实现这样的东西的真正好处是什么?

EN

回答 3

Stack Overflow用户

发布于 2014-09-18 09:26:12

正如其他人所指出的,ASP.NET上的async的意义在于它释放了ASP.NET线程池中的一个线程。这对于自然异步操作非常有效,比如I/O绑定操作,因为服务器上的线程减少了一个(没有线程在“处理”异步操作,as I explain on my blog)。因此,async在服务器端的主要好处是可伸缩性。

但是,你要避免在ASP.NET上使用Task.Run (更糟糕的是,Task.Factory.StartNew),我称之为“伪异步”,因为它们只是在线程池线程上进行同步/阻塞工作。它们在UI应用程序中很有用,在这些应用程序中,您希望将工作从UI线程中推送出去,以便UI保持响应,但它们(几乎)不应该在ASP.NET或其他服务器应用程序上使用。

在ASP.NET上使用Task.RunTask.Factory.StartNew实际上会降低可伸缩性。它们会导致一些不必要的线程切换。对于运行时间更长的操作,最终可能会丢弃ASP.NET线程池试探法,从而导致创建额外的线程,然后不必要地销毁这些线程。我将一步一步地研究这些性能问题,in another blog post

因此,您需要考虑每个操作都在做什么,以及这些操作是否应该是异步的。如果应该,那么该操作应该是异步的。在您的案例中:

代码语言:javascript
复制
public HttpResponseMessage Get()
{
  var data = _userServices.GetUsers();
  return Request.CreateResponse(HttpStatusCode.OK, data);
}

Request.CreateResponse到底在做什么?它只是在创建响应对象。就是这样--就是一个花哨的new。那里没有I/O,当然也不需要推到后台线程。

然而,GetUsers要有趣得多。这听起来更像是基于I/O的数据读取。如果你的后端可以扩展(例如,Azure SQL / Tables /等),那么你应该首先考虑创建async,一旦你的服务公开了一个GetUsersAsync,那么这个操作也可能变成async

代码语言:javascript
复制
public async Task<HttpResponseMessage> Get()
{
  var data = await _userServices.GetUsersAsync();
  return Request.CreateResponse(HttpStatusCode.OK, data);
}
票数 29
EN

Stack Overflow用户

发布于 2014-09-18 08:21:13

调用发生在主要IO操作的位置更有意义。是的,异步更快,因为它在执行操作时释放了请求线程。因此,从Web服务器的角度来看,您正在将一个线程返回给池,服务器可以使用该线程池进行将来的任何调用。

因此,例如,当您在SQL server上执行搜索操作时,您可能希望执行异步操作,并查看性能优势。

它对于涉及多个服务器的可扩展性是很好的。

因此,例如,当SearchRecordAsync将其SQL发送到数据库时,它返回一个未完成的任务,而当请求命中await时,它将请求线程返回到线程池。稍后,当DB操作完成时,将从线程池中获取一个请求线程,并使用该线程继续请求。

即使您没有使用SQL操作,假设您想要发送一封电子邮件给10个人。在这种情况下,异步也更有意义。

Async还可以非常方便地显示长事件的进度。因此,当任务在后台运行时,用户仍将获得活动的GUI。

要了解这一点,请看此示例。

在这里,我正在尝试启动名为“发送邮件”的任务。临时我想更新数据库,而后台正在执行发送邮件任务。

数据库更新完成后,它将等待发送邮件任务完成。然而,使用这种方法,很明显我可以在后台运行任务,同时仍然使用原始(主)线程。

代码语言:javascript
复制
using System;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Starting Send Mail Async Task");
        Task task = new Task(SendMessage);
        task.Start();
        Console.WriteLine("Update Database");
        UpdateDatabase();

        while (true)
        {
            // dummy wait for background send mail.
            if (task.Status == TaskStatus.RanToCompletion)
            {
                break;
            }
        }

    }

    public static async void SendMessage()
    {
        // Calls to TaskOfTResult_MethodAsync
        Task<bool> returnedTaskTResult = MailSenderAsync();
        bool result = await returnedTaskTResult;

        if (result)
        {
            UpdateDatabase();
        }

        Console.WriteLine("Mail Sent!");
    }

    private static void UpdateDatabase()
    {
        for (var i = 1; i < 1000; i++) ;
        Console.WriteLine("Database Updated!");
    }

    private static async Task<bool> MailSenderAsync()
    {
        Console.WriteLine("Send Mail Start.");
        for (var i = 1; i < 1000000000; i++) ;
        return true;
    }
}
票数 2
EN

Stack Overflow用户

发布于 2014-09-18 08:34:06

在服务器上使用async可以极大地提高可伸缩性,因为它可以释放为请求提供服务的线程,以便在async操作进行时处理其他请求。例如,在同步IO操作中,线程将被挂起,并且在操作完成之前什么也不做,并且不能为另一个请求提供服务。

也就是说,使用Task.Factory.StartNew 会启动另一个线程,所以您根本得不到可伸缩性的好处。您的原始线程可以重用,但您已将工作卸载到另一个线程,因此根本没有任何净收益。实际上,切换到另一个线程是有成本的,但这是最小的。

真正的异步操作不会启动线程,我会查看是否存在这样的操作,或者是否可以为Request.CreateResponse编写这样的操作。那么你的代码就会变得更具伸缩性。如果不是这样,您最好坚持使用同步方法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25902275

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档