1

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.

Master117
  • 660
  • 6
  • 21
  • 1
    Never use '.Result' you should 'await command.Hash()' – IeuanW Feb 01 '20 at 12:16
  • @IeuanW but then I have to make this method async, all the way to the top, but Application_Start() isn't async. – Master117 Feb 01 '20 at 14:42
  • if you use DI you wouldn't need to add anything to the startup. i.e. if you use a singleton then the entire class would be ready and waiting for other callers to use. – IeuanW Feb 03 '20 at 09:53

2 Answers2

1

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.

Simon
  • 413
  • 5
  • 14
0

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;
}
Master117
  • 660
  • 6
  • 21