Вызов нескольких методов асинхронно в одном методе в ASP.NET MVC Controller - PullRequest
0 голосов
/ 13 мая 2019

В приложении ASP.NET MVC в моем Service.cs есть два метода, как показано ниже (для краткости методы упрощены), и я хочу вызывать эти методы асинхронно, используя async. Но после вызова первого метода (Save) из Controller я тоже хочу вернуть результат этого действия, не дожидаясь второго метода (SendEmail). Но в этом случае я должен вернуть результат и не знаю, как управлять этим с помощью ASP.NET MVC async. Не могли бы вы дать некоторые предложения по этому сценарию? Я думаю, что я должен использовать async во всех методах цепочки, но не уверен, как построить эту цепочку. Любая помощь будет оценена.

Контроллер:

public JsonResult AddRecord() {
var result = service.Save();
//I need to return the result after record is added (without waiting the email sent)

service.SendEmail();    
}

Услуги:

public MyEntity Save() {
    //
}


public void SendEmail() {
    //
}

Ответы [ 4 ]

2 голосов
/ 13 мая 2019

Сценарии, о которых я могу думать. используя анонимную задачу

public JsonResult AddRecord() {
var result = service.Save();
//I need to return the result after record is added (without waiting the email sent)

Task.Run(() => service.SendEmail()); 
return result;
}

Второй сценарий - сделать ваш метод SendEmail асинхронным, таким образом, он будет почти таким же, как задача, обычно, говорят, что использование асинхронных методов не очень хорошая идея, но я думаю, что этот конкретный сценарий соответствует критериям

1 голос
/ 13 мая 2019

вы можете попробовать сделать это:

public class Service
{
    public Task<MyEntity> SaveAsync()
    {
        return Task.Run(() => Save());
    }

    public MyEntity Save()
    {
        Thread.Sleep(2000);
        var entity = new MyEntity();
        return entity;
    }

    public Task SendEmailAsync()
    {
        return Task.Run(() => SendEmail());
    }

    public void SendEmail()
    {
        Thread.Sleep(2000);
        Console.WriteLine("The message is sent");
    }
}

и создайте контроллер, или другой сервис, какой-нибудь такой:

public class SomeController
{
    private readonly Service _service;

    public SomeController()
    {
        _service = new Service();
    }

    public MyEntity AddRecord()
    {
        var resultTask = _service.SaveAsync();
        _service.SendEmailAsync();

        return resultTask.Result;
    }

    public async Task<MyEntity> AddRecord2()
    {
        var resultTask = _service.SaveAsync();

        _service.SendEmailAsync();

        //var result = await resultTask;
        //return result;

        return await resultTask;
    }
}
0 голосов
/ 13 мая 2019

Один из подходов заключается в изменении поведения SendEmail и его имени, чтобы оно фактически не отправляло электронное письмо.Добавляет запрос на отправку электронного письма в очередь.Ваш вызов метода может выглядеть следующим образом:

service.QueueEmail(someData);

Нет необходимости в том, чтобы это было асинхронным (и бесполезным), потому что все, что вы делаете, - это добавление чего-либо в очередь.Отдельный процесс читает из очереди и отправляет электронные письма.

Это приведет к тому, что ваш сервис станет более сфокусированным.Более подробный код, который знает, как отправить электронное письмо, будет жить в другом месте.Затем этот код может обрабатывать эту сложность более эффективно.Например, он может включать логику повторных попыток.И поскольку у вас есть другие процессы в вашем приложении, которые отправляют электронные письма, они могут повторно использовать этот процесс.

0 голосов
/ 13 мая 2019

Звучит так, как будто вы хотите вызвать SendMail () из другого потока. Попробуйте поискать Hangfire , который помогает с фоновыми заданиями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...