C# 在ASP.NET 4.5中使用部分异步/等待代码等待异步lambda
我在asp.net中有一个HTTPHandler,我想使用4.5异步等待代码将其转换为异步。然而,并非所有代码都是4.5版本,因此我们的应用程序库、基础设施的内部部分目前需要保持在4.0版本。我遇到了一个问题,我想为我们的一些共享库提供一个lambda。lambda是异步的,但是我需要库代码来等待它完成,但是没有死锁。到目前为止我还没有弄明白 假设处理程序如下所示:C# 在ASP.NET 4.5中使用部分异步/等待代码等待异步lambda,c#,asp.net,.net-4.0,async-await,.net-4.5,C#,Asp.net,.net 4.0,Async Await,.net 4.5,我在asp.net中有一个HTTPHandler,我想使用4.5异步等待代码将其转换为异步。然而,并非所有代码都是4.5版本,因此我们的应用程序库、基础设施的内部部分目前需要保持在4.0版本。我遇到了一个问题,我想为我们的一些共享库提供一个lambda。lambda是异步的,但是我需要库代码来等待它完成,但是没有死锁。到目前为止我还没有弄明白 假设处理程序如下所示: // .NET 4.5 website public class MyHandler : HttpTaskAsyncHandler
// .NET 4.5 website
public class MyHandler : HttpTaskAsyncHandler
{
public override async Task ProcessRequestAsync(HttpContext context)
{
var someLibrary = new SharedLibrary();
someLibrary.PostProcess = async (x,y) => {
await ProcessXY(x,y);
}
await someLibrary.ProcessAsync();
// write out some content here
}
private async Task ProcessXY(int x, int y) {
// make some external calls
var someLib = new SomeOtherLibrary();
await someLib.CallAsync(x,y);
}
}
// .NET 4.0 class library
public class SharedLibrary {
public Action<int,int> PostProcess { get; set; }
public Task ProcessAsync() {
return Task.Factory.StartNew(() => Process(), CancellationToken.None,TaskCreationOptions.None,TaskScheduler.FromCurrentSynchronizationContext());
}
public void Process() {
// do some processing
if (PostProcess != null) {
// call PostProcess synchronously
PostProcess(1,2);
}
// do some final processing
}
}
然后SharedLibrary看起来像这样:
// .NET 4.5 website
public class MyHandler : HttpTaskAsyncHandler
{
public override async Task ProcessRequestAsync(HttpContext context)
{
var someLibrary = new SharedLibrary();
someLibrary.PostProcess = async (x,y) => {
await ProcessXY(x,y);
}
await someLibrary.ProcessAsync();
// write out some content here
}
private async Task ProcessXY(int x, int y) {
// make some external calls
var someLib = new SomeOtherLibrary();
await someLib.CallAsync(x,y);
}
}
// .NET 4.0 class library
public class SharedLibrary {
public Action<int,int> PostProcess { get; set; }
public Task ProcessAsync() {
return Task.Factory.StartNew(() => Process(), CancellationToken.None,TaskCreationOptions.None,TaskScheduler.FromCurrentSynchronizationContext());
}
public void Process() {
// do some processing
if (PostProcess != null) {
// call PostProcess synchronously
PostProcess(1,2);
}
// do some final processing
}
}
正如代码所示,在lambda完全运行之前,对PostProcess的调用将返回。如果我将PostProcess改为Func,并作为PostProcess1,2.Wait调用,则会死锁。有没有一种方法可以在混合的4.5/4.0代码中实现这样的功能?在lambda中使用configurewaitfalse:
public override async Task ProcessRequestAsync(HttpContext context)
{
var someLibrary = new SharedLibrary();
someLibrary.PostProcess = async (x,y) => {
await ProcessXY(x,y).ConfigureAwait(false);
}
await someLibrary.ProcessAsync();
// write out some content here
}
public class SharedLibrary {
public Func<int,int,Task> PostProcess { get; set; }
public void Process() {
// do some processing
if (PostProcess != null) {
// call PostProcess synchronously
PostProcess(1,2).Wait();
}
// do some final processing
}
}
这样,您应该避免UI线程上的死锁
编辑
如注释中所述,一旦在ASP.NET中使用ConfigureWaitFalse,HttpContext在continuation中就不再可用
等待后编码
我建议您查看通过Nuget为.NET 4部署的Microsoft.Bcl.Async库,这样您就可以正确使用Async/await,而无需出于任何原因初始化线程:
只要仍在使用C5.0,就可以在.NET4.0中使用await,即使不能使用await,也可以在.NET4.0中编写异步程序,这只是需要做更多的工作,而且做得很好。您的4.0代码不需要同步。请尝试为Process方法指定一个返回类型,我认为这将强制运行时等待它实际返回。您需要ProcessXY在//进行最终处理之前完成,还是只需要在//在此写出一些内容之前完成?是的,ProcessXY需要在最终处理之前完成。进程获取分布式锁这不是CLR锁,后处理对数据进行一些附加修改。最后的处理是保存然后释放锁。这很有效。需要注意的一点是,由于configureWaitFalse,lambda将无法访问ASP.NET上下文。幸运的是,我可以在这个例子中解决这个问题。对,我忘了提那个!编辑我的帖子。