Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在ASP.NET 4.5中使用部分异步/等待代码等待异步lambda_C#_Asp.net_.net 4.0_Async Await_.net 4.5 - Fatal编程技术网

C# 在ASP.NET 4.5中使用部分异步/等待代码等待异步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

我在asp.net中有一个HTTPHandler,我想使用4.5异步等待代码将其转换为异步。然而,并非所有代码都是4.5版本,因此我们的应用程序库、基础设施的内部部分目前需要保持在4.0版本。我遇到了一个问题,我想为我们的一些共享库提供一个lambda。lambda是异步的,但是我需要库代码来等待它完成,但是没有死锁。到目前为止我还没有弄明白

假设处理程序如下所示:

// .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上下文。幸运的是,我可以在这个例子中解决这个问题。对,我忘了提那个!编辑我的帖子。