【问题标题】:MVC4- An asynchronous operation cannot be started at this time --- code works fine on MVC3MVC4-此时无法启动异步操作 --- 代码在 MVC3 上运行良好
【发布时间】:2014-07-06 16:18:07
【问题描述】:

我将一个项目从 MVC3 转换为 MVC4,并从 Entity Framework 5 转换为 EF 6.1。在代码中有一个 VBHTML 页面,其中有一个代码部分“使用 Html.BeginForm.... 结束使用”。在此页面中,用户可以选择一个文件并单击提交。这会在控制器中调用 POST 方法。控制器中的方法使用 GData API 的可恢复上传器(异步)将所选文件上传到 Google 驱动器。必须使用 ResumableUploader(上传 PDF 和大文件的 GData API 限制)。现在,这段代码过去在 MVC3 中一直有效。一旦平台更改为 MVC4,就开始出现此异常:

此时无法启动异步操作。异步操作只能在异步处理程序或模块内或在页面生命周期中的某些事件期间启动。如果在执行 Page 时发生此异常,请确保将 Page 标记为

at System.Web.AspNetSynchronizationContext.OperationStarted() at Google.GData.Client.ResumableUpload.ResumableUploader.AsyncStarter
(AsyncResumableUploadData data, WorkerResumableUploadHandler workerDelegate, 
Object userData)

我确实将@Page Async="true" 放在了VBHTML 页面中,但这并没有帮助。我 100% 确定这与 MVC4 和/或 .Net 4.5 有关,因为代码中没有进行其他更改(除了迁移到 MVC4 和迁移到 .Net4.5 之外)。我现在有两个代码分支,一个在 MVC3 上,一个在 MVC4 上。当我编译 MVC3 并在应用程序中复制输出 DLL 时,上述问题并未浮出水面。当我用 MVC4 版本替换该 DLL 时,出现了上述问题。如何处理?

这是导致此问题的代码:

Dim auth As Authenticator = New AuthSubAuthenticator("MyToken", authFactory.Token)
Dim uploader As New ResumableUploader(10485760)
AddHandler uploader.AsyncOperationCompleted, AddressOf UploaderCompleted
uploader.InsertAsync(auth, file, New Object())

跟踪显示异常是从最后一行(uploader.InsertAsync)抛出的


我知道有一个 await 方法可以使用。没有尝试,而是将uploader.InsertAsync 更改为uploader.Insert 并且代码可以正常工作。但是用户必须等到上传完成(对于较大的文件,需要很长一段时间)。

【问题讨论】:

    标签: asp.net-mvc-4 asynchronous


    【解决方案1】:

    我 100% 确定这与 MVC4 和/或 .Net 4.5 相关

    是的,这是 ASP.NET 4.5 中的一个变化。但是,重要的是要注意之前的代码在技术上是错误的。 ASP.NET 4.5 添加了一些保护措施来捕获不正确的异步使用。因此,MVC3 代码实际上是不正确的;它只是没有被抓住和报告。

    将 uploader.InsertAsync 更改为 uploader.Insert 并且代码可以正常工作。但是用户必须等到上传完成(对于较大的文件,需要很长一段时间)。

    这是在 ASP.NET 上执行此操作的“正确”方式(附带说明,使用 await 将比 Insert 更有效)。 ASP.NET 不适合在没有用户连接的情况下工作。

    考虑一下,例如,如果上传出错会发生什么;无法通知用户上传实际上没有完成。就此而言,无法通知用户上传已完成。此外,ASP.NET 可能会回收您的应用程序,这可能会终止正在进行的上传。由于这些原因,不建议在 ASP.NET 上执行“一劳永逸”的工作。

    但是,如果您愿意忍受这些限制,我会在我的博客中描述多种方法来实现fire and forget on ASP.NET。请注意,ASP.NET 4.5.2 添加了一种内置方式来执行此操作:HostingEnvironment.QueueBackgroundWorkItem

    【讨论】:

    • 恕我直言,这似乎不是他们决定做出如此重大改变的原因。即使程序在后台运行,程序员也可以处理“如果上传错误会发生什么”。回调函数可以轻松地在 UI 上显示消息以通知用户出现问题。如果出现错误,可能还有许多其他方法可以通知用户。如果您的理论是正确的,为什么 .net 不强制程序员捕获所有错误并通知用户。
    • 我可以轻松捕获所有错误并忽略它们。 .Net 可以对此做些什么吗?每次我们从一个版本升级到另一个版本时,我们都会在这样的愚蠢事情上花费数十个小时。不幸的是,尽管在市场上呆了这么久,MS 人还没有学会如何编写软件。
    • 所以基本上你是说在.Net中使用线程本质上是错误的。在 .Net 中启动工作线程本质上是错误的?所以基本上 Azure 的工作者角色本质上是错误的,因为最终,这些工作者需要被用户可能做的事情触发。
    • 事实上,他们自己的规范声明在页面中使用 Async =true 会解决这个问题。但是,怎么不行呢?
    • @AllenKing:线程没有问题,但线程错误肯定有问题。 ASP.NET 在设计时并未考虑到应用程序级工作线程,但在技术上可以使用它们。 Azure 辅助角色完全不同,因为它们不是托管在 ASP.NET 中。
    猜你喜欢
    • 2016-05-14
    • 2019-01-11
    • 2022-09-28
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    相关资源
    最近更新 更多