我有一个很长的运行过程,通过Nancy Module Get方法调用。我不希望浏览器在进程运行时挂起,而是希望此调用是异步的,换句话说,我希望Get方法立即返回,并让长时间运行的进程完成它的工作。然后我可以定期检查过程的状态并采取相应的行动。如何使用C#5 async/await从asp.net托管模块调用异步进程?
我是C#5的异步/等待功能的新手,但我确信这些是为了这种任务而设计的。下面的代码显示了我的尝试。我已经放入了一些记录,表明它不像预期的那样异步运行。长时间运行的进程阻止Get方法,因此浏览器挂起。
模块
public class TestModule : NancyModule
{
public TestModule(ITestService testService)
{
Get["/longprocess"] = _ =>
{
Log.Write("Module : Start");
testService.LongProcess();
Log.Write("Module : Finish");
return HttpStatusCode.OK;
};
}
}
服务
public interface ITestService
{
Task<bool> LongProcess();
}
public class TestService : ITestService
{
public async Task<bool> LongProcess()
{
await LongProcessAsynch();
return true;
}
private Task<bool> LongProcessAsynch()
{
Log.Write("LongProcess : Start");
Thread.Sleep(5000);
//Task.Delay(5000); <- Has same effect
Log.Write("LongProcess : Finish");
return true.AsTask();
}
}
扩展方法
public static Task<T> AsTask<T>(this T candidate)
{
var source = new TaskCompletionSource<T>();
source.SetResult(candidate);
return source.Task;
}
日志输出
14/06/2012 19:22:29 : Module : Start
14/06/2012 19:22:29 : LongProcess : Start
14/06/2012 19:22:34 : LongProcess : Finish
14/06/2012 19:22:34 : Module : Finish
您可以从日志输出的LongProcess()
看到上面挡住了获取模块的回报。如果任务异步运行我希望在日志中是这个样子:
预计登录
Module : Start
LongProcess : Start
Module : Finish
LongProcess : Finish
我认为什么是真正需要的是把await
在NancyModule获取方法。像下面也许是代码的东西,但我不能这样做,因为我不能标记模块构造为asnyc
,所以我不能Get方法中使用await
(或所以我现在相信)
Get["/longprocess"] = _ =>
{
Log.Write("Module : Start");
await testService.LongProcess();
Log.Write("Module : Finish");
return HttpStatusCode.OK;
};
感谢您的帮助,示例或指向资源的指针。
编辑1
更多的研究表明,asp.net似乎积极预防async
调用默认。与Session
和我认为处理非UI线程的方式有关。所以我添加了以下到我的web.config(见下文)
- UseTaskFriendlySynchronizationContext
- ENABLESESSIONSTATE = “假”
不幸的是,没有任何区别,我的async
/await
调用LongProcess()
仍然阻塞。
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
<add key="webPages:Enabled" value="false" />
</appSettings>
<system.web>
<httpRuntime targetFramework="4.5"/>
<pages controlRenderingCompatibilityVersion="4.0" enableSessionState="false" />
... more config
</configuration>
我不知道NancyFX是什么,但它需要支持任务的返回值,为您使用它异步。 – usr
我嵌套异步调用尝试解决此问题。对'testService.LongProcess()'的初始调用是同步的,但是这会使用'await'关键字调用'LongProcessAsynch()'方法,所以这应该是异步的。你认为这是正确的吗? – biofractal