简体   繁体   中英

Correct Way to use an async Library with ASP.NET/MVC/REST

I have an async Library for audio file processing. Furthermore I want to offer these Methods via Rest. So I made an MVC WebApi Project. The library needs some time to start, so I added a class that offers a way to init and exposes the libraries main object.

public static class MusicHandler
{
    public static MusicCapture.MusicCapture MusicCapture;
    public static void init()
    {
        MusicCapture = new MusicCapture.MusicCapture("D:\\Temp", "D:\\test", "E:\\FingerPrintDB2.ss");
        MusicCapture.Start();
    }
}

I start it in Application_Start()

protected void Application_Start()
{
    MusicHandler.init();
}

Now when my init method contains some async calls like this:

var hashedFingerprints = command.Hash().Result;

The programm will just skip over these lines. They do not get executed for all I can tell. Same thing happens when I call any of the objects async methods from my REST endpoints. When I run the library not from ASP.NET/MVC the code works flawlessly.

I found some comments that said that this is a problem because of deadlocks, but no advice or code how to avoid this/make this work.

Thank you in advance.

So, if I understand, you want to start something called a MusicHandler , which takes a little while to start up. Once that has loaded, communication with your system will be via RESTful HTTP calls.

In your MusicHandler you can have a flag to state whether it has finished loading.

public static class MusicHandler
{
    public static MusicCapture.MusicCapture MusicCapture;
    public static bool Initialized {get;} = False;
    public static void init()
    {
        MusicCapture = new MusicCapture.MusicCapture("D:\\Temp", "D:\\test", "E:\\FingerPrintDB2.ss");
        MusicCapture.Start();
        Initialized = true;
    }
}

Then in your MVC Controller, you can examine this flag and return an error if initialization has not completed.

This way you don't need to worry about being async all the way to the top.

But I'm surprised you're using application_start at all... host this using kestrel and do this setup in program.cs or something, where you can be async to the top natively.

I figured my Problem out, it was twofold.

  1. My library failing on start was a bug in the library that led to an exception which wasn't bubble up. I was able to mitigate this bug. Async calls on startup with a MVC App with .Result inside seem to actually be no problem.

  2. My REST calls failing on async could be fixed by changing the rest controllers methods to async. I never would have thought thats possible but I found an example here: https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

// GET api/music
public async System.Threading.Tasks.Task<string> GetAsync()
{
    string result = await MusicHandler.MusicCapture.DetectAsync(5);
    Console.WriteLine("Server returning: " + result);
    return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM