我在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);
答案 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
方法,但我非常确定此代码中的瓶颈是数据库访问。