如何使序列化的Async Result工作

时间:2016-02-26 19:12:24

标签: c# asp.net async-await

我在ASP.NET MVC异步控制器中使用了以下内容。我意识到我正在尝试序列化一项任务。我不想打电话给speakerAll1.Result,因为这似乎违背了异步的目的。

是否有正确的异步方式可以实现此序列化?

    public async Task<ActionResult> Index()
    {
        Task<List<Speaker>> speakersAll1 =
                            _context.
                                Speakers.
                                Include(a => a.Sessions.
                                    Select(b => b.Tenant)).
                                ToListAsync();

        foreach (var speaker in await speakersAll1)
        {
            speaker.ImageUrl = "#";
        }

        byte[] objectDataAsStream;
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        using (MemoryStream memoryStream = new MemoryStream())
        {
            binaryFormatter.Serialize(memoryStream, speakersAll1);
            objectDataAsStream = memoryStream.ToArray();
        }

        return View("Index", "_Layout", objectDataAsStream.Length);
    }

错误:

Type 'System.Threading.Tasks.Task`1[[System.Collections.Generic.List`1[[WebApp.Models.Speaker, WebApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' in Assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.

答案:根据@Gusman更改binaryFormatter,如下所示:

binaryFormatter.Serialize(memoryStream, await speakersAll1);

1 个答案:

答案 0 :(得分:0)

您根本无法序列化Task,您真正想要的是序列化结果。

ASP.NET MVC 控制器中的异步方法可以更好地使用线程池。当请求进入时,ASP.NET接受其中一个线程池线程并将其分配给该请求。当需要外部I / O操作时,请求线程将返回到线程池,直到对外部资源的调用返回。

重要区别在于异步调用正在进行时请求线程已返回到线程池。当线程在线程池中时,它不再与该请求相关联。

异步请求允许较少数量的线程处理大量请求。

使用此代码:

public async Task<ActionResult> Index()
{
    List<Speaker> speakersAll1 = await _context.Speakers
                                                .Include(a => a.Sessions.Select(b => b.Tenant))
                                                .ToListAsync();

    foreach (var speaker in speakersAll1)
    {
        speaker.ImageUrl = "#";
    }

    byte[] objectDataAsStream;
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    using (MemoryStream memoryStream = new MemoryStream())
    {
        binaryFormatter.Serialize(memoryStream, speakersAll1);
        objectDataAsStream = memoryStream.ToArray();
    }

    return View("Index", "_Layout", objectDataAsStream.Length);
}

执行await ... ToListAsync()时,线程被释放而不是阻塞,允许它处理另一个请求。

此代码与您的代码相同,因为您在await循环中调用foreach但它更清晰一点。

此外,在await之后您可以使用Result属性,因为此时任务已经完成。

也许您可以将代码的一部分移动到async方法,但我非常确定此代码中的瓶颈是数据库访问。