Safe way to call async method in EPiServer scheduled job?

Vote:
 

Hi!

Can anyone give an example of how to safely call an async method in an EPiServer scheduled job?

The following is - as far as I know - not safe:

IDummyRepository repo = new DummyRepository();
var dummies = repo.GetDummiesAsync().Result;
#204063
May 17, 2019 14:51
Vote:
 

Yes calling Result just forces the Asnc job to run and return a result so it's the correct way when returning a result. If you're calling an method with just Task you can then call .Wait()

#204066
May 17, 2019 15:36
Vote:
 

FYI I use this way heavily in some very complex Jobs and they work fine. It's also best practice to make sure to use the OnStatusChanged() method to update the Job so if you're using an Asnc job you can pass in a progress indicator object that can return back data as the asnc method does it's work then pass that through to the OnStatusChanged()  therefore updating the user on the progress of the job. Great for large operations

#204067
May 17, 2019 15:39
Vote:
 

Yeah running async method you should ideally run it all the way up but not possible for scheduled job which...runs in a separate thread anyway so. 

I would go with .Result and .Wait() if you have no matching synchronous methods. 

You can avoid some deadlock issues by using .ConfigureAwait(false) on your await calls. So if you are building your own async library that is often a good idea to avoid some issues. 

var response = await _client.SendAsync(message).ConfigureAwait(false);
#204069
May 17, 2019 15:57
Vote:
 

give this a try.

public static class AsyncHelper
{
    private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None,
                                                                            TaskCreationOptions.None,
                                                                            TaskContinuationOptions.None,
                                                                            TaskScheduler.Default);

    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
    {
        return _myTaskFactory.StartNew(func)
                                .Unwrap()
                                .GetAwaiter()
                                .GetResult();
    }

    public static void RunSync(Func<Task> func)
    {
        _myTaskFactory.StartNew(func)
                        .Unwrap()
                        .GetAwaiter()
                        .GetResult();
    }
}

then you can call your async method in sync context in a little bit more "friendly fashion".

#204087
Edited, May 18, 2019 4:38
Vote:
 
#204092
May 19, 2019 21:56
Vote:
 

Hi Markus,

The Below codes helps me a lot,

      Task.Run(async () => await serviceHelper.GetProductDetails(productCode))?.Result;

You can use the same on EPiServer scheduled job.

#204177
May 21, 2019 16:22
Vote:
 

@Vetrivel, don't do that because you will get back `System.AggregateException` and not the actual error underneath.

#204182
May 21, 2019 19:05
Vote:
 

Thanks everyone!

I decided to use the AsyncHelper-class.

Hopefully it'll be better than just calling "...Result;".

#204297
May 24, 2019 13:24