Асинхронный вызов метода с помощью Task.Run

Может ли кто-нибудь помочь мне, как сделать вызов метода SendSms(textMessageItems) асинхронным? Какой лучший метод/практика? Я предполагаю, что здесь можно использовать Task.Run Async-Await, поскольку я использую .Net4.5 с использованием MVC4 WebApi. Но я хотел бы услышать от экспертов, поскольку я новичок в этом. Я использую этот код на своем веб-сервере, который находится в IIS7, и этот метод может занять некоторое время для обработки, и поэтому я хотел бы обрабатывать его асинхронно, чтобы ответ мог сразу вернуться вызывающему. Кроме того, поскольку я вызываю SendSms внутри цикла for, вызовет ли это какие-либо проблемы? Как вы думаете, я должен передать его как список коллекции, а затем обработать? Пожалуйста, порекомендуйте.

 using Twilio.Mvc;
 using Twilio.TwiML.Mvc;
 using Twilio.TwiML;


public class SmsController : ApiController
{
    [HttpPost]
    public HttpResponseMessage Post([FromBody]SmsRequest smsReq)
    {
            var response = new Twilio.TwiML.TwilioResponse();
            //validation checks..

            try
            {


                if ((txtMessageResponse != null) && (txtMessageResponse.SmsMessageInfo.Count > 0))
                {
                    _smsStagingList = txtMessageResponse.SmsMessageInfo;
                    foreach (TextMessageStaging prepareTextMessageResponse in _smsStagingList)
                    {
                        smsDTO textMessageItems = new smsDTO();
                        textMessageItems.PhoneNumber = prepareTextMessageResponse.PhoneNumber;
                        textMessageItems.SmsMessage = prepareTextMessageResponse.SmsMessageBody;

                        isTxtMessageSent = SendSms(textMessageItems);

                        //If the messages were sent then no need to set the flag to be updated 
                        if (isTxtMessageSent)
                        {
                            txtMessageStatusToBeUpdated = false;
                        }
                    }
                    return Request.CreateResponse(HttpStatusCode.OK, twilioResponse.Element);
                }
                else
                {
                    //send error response
                }
            catch (Exception msgProcessingError)
            {
              //send error response again as processing error
            }
            finally
            {
             //set the outbound flag in the table
            }
     }


    private bool SendSms(smsDTO textMessageItems)
    {
        bool isTxtMessageSent = false;
        PushMessageRequest txtMessageRequest = new PushMessageRequest();
        PushMessageResponse txtMessageResponse = null;
        txtMessageRequest.SmsMessageInfo = new SendTextMessage(); //instantiate the dto

        txtMessageRequest.SmsMessageInfo.ToPhone = textMessageItems.PhoneNumber;
        txtMessageRequest.SmsMessageInfo.TextMessage = textMessageItems.SmsMessage;
        try
        {
            using (ITextService textService = ObjectFactory.SendSmsMessage())
            {
                txtMessageResponse = textService.SendSmsMessage(txtMessageRequest);
            }

            isTxtMessageSent = txtMessageResponse.IsSuccessful;
        }
        catch (Exception ex)
        {
            isTxtMessageSent = false;
        }      
        return isTxtMessageSent;
    }          

person Ditty    schedule 28.01.2014    source источник


Ответы (1)


Я рекомендую вам не использовать Task.Run. Насколько я знаю, у Twilio нет async API, поэтому вы должны спросить их об этом. Конечно, вы можете написать свой собственный, например, на основе HttpClient.

хотел бы обработать его асинхронно, чтобы ответ мог сразу вернуться к вызывающей стороне

Обратите внимание, что async не изменяет протокол HTTP как описано в моем блоге. возможно, но крайне опасно, вернуть ответ от ASP.NET, пока запрос не закончил обработку (также ссылка на мой блог).

person Stephen Cleary    schedule 28.01.2014
comment
На самом деле ответ будет только ответом HTTP OK и ничем другим. Ответ на входящий текст отправляется через исходящий текст и фактически не привязан к входящему тексту. Об этой части заботится textService.SendSmsMessage. Имеет ли это смысл? - person Ditty; 29.01.2014
comment
@Ditty: Да, и мой совет остается в силе. Это по-прежнему крайне опасно. Ваша веб-служба должна просто хранить данные запроса в надежной очереди (например, очередь Azure или MSMQ), а отдельные серверные процессы должны отправлять SMS-ответы (например, рабочая роль Azure или служба Win32). - person Stephen Cleary; 29.01.2014
comment
Так что даже если это пожар и забыть вид вызова вы бы все равно посоветовали то же самое? Я видел в вашей статье blog.stephencleary.com/2012 /12/ в вопросах и ответах вы упомянули что-то об использовании Async с ожиданием. Будет ли это в любом случае работать здесь или все еще не рекомендуется? - person Ditty; 29.01.2014
comment
@Ditty: Вы можете использовать async и await просто отлично. Но он не вернет ответ вызывающему абоненту. - person Stephen Cleary; 29.01.2014
comment
Вы имеете в виду, что сервер будет ждать завершения асинхронного процесса из-за ожидания, прежде чем он отправит ответ HTTP обратно? Это то, что вы имели в виду? - person Ditty; 29.01.2014
comment
@Ditty: Да, сервер будет ждать завершения обработчика async. - person Stephen Cleary; 29.01.2014