задание backgroud для отправки смс asp.net core 2.2 - PullRequest
0 голосов
/ 29 марта 2019

Мне нужно отправить смс в фоновом режиме. Для этого я использую функцию HostedService для Asp.Net Core 2.x. Но приложение не может запуститься правильно. У меня есть работающий SMS-сервер. Я отправляю HTTP-запрос на этот сервер для отправки смс.

Вот мой интерфейс:

public interface ISmSHandlerForCashBaba
    {
        void SendSMS(string mobileNumber, string message);
    }

Вот мой код реализации

public class SmSHandlerForCashBaba : ISmSHandlerForCashBaba, IHostedService, IDisposable
    {
        //The BufferBlock<T> is a thread-safe producer/consumer queue
        private readonly IConfiguration _configuration;
        private readonly ILogger logger;
        private readonly IHttpClientFactory _clientFactory;
        private string FullUrl;
        private Task sendTask;
        private CancellationTokenSource cancellationTokenSource;
        public SmSHandlerForCashBaba(IHttpClientFactory clientFactory, IConfiguration configuration, ILogger<SmSHandlerForCashBaba> logger)
        {
            _clientFactory = clientFactory;
            _configuration = configuration;
            this.logger = logger;
        }



        public Task StartAsync(CancellationToken cancellationToken)
        {
            logger.LogInformation("Starting background e-mail delivery");
            cancellationTokenSource = new CancellationTokenSource();
            //The StartAsync method just needs to start a background task (or a timer)
            sendTask = Send(cancellationTokenSource.Token);
            return Task.CompletedTask;
        }
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            //Let's cancel the e-mail delivery
            CancelSendTask();
            //Next, we wait for sendTask to end, but no longer than what the web host allows
            await Task.WhenAny(sendTask, Task.Delay(Timeout.Infinite, cancellationToken));
        }

        private void CancelSendTask()
        {
            try
            {
                if (cancellationTokenSource != null)
                {
                    logger.LogInformation("Stopping e-mail background delivery");
                    cancellationTokenSource.Cancel();
                    cancellationTokenSource = null;
                }
            }
            catch
            {

            }
        }

        //This public method will be used by other services (such as a Controller)
        //to post messages to the email sender service.
        //They will be sent asynchronously in background
        //TODO: make the Post method return an operation Guid so that the client can
        //check whether the e-mail has been sent or not at a later time
        public void SendSMS(string mobileNumber, string message)
        {
            var builder = new UriBuilder(_configuration["SmsService:url"]);
            NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
            query["Username"] = _configuration["SmsService:userName"];
            query["Password"] = _configuration["SmsService:password"];
            query["To"] = mobileNumber;
            query["Message"] = message;
            builder.Query = query.ToString();
            FullUrl = builder.ToString();

        }

        public async Task Send(CancellationToken token)
        {
            logger.LogInformation("E-mail background delivery started");

            while (!token.IsCancellationRequested)
            {

                try
                {
                    var request = new HttpRequestMessage(HttpMethod.Get, FullUrl);
                    //Let's wait for a message to appear in the queue
                    //If the token gets canceled, then we'll stop waiting
                    //since an OperationCanceledException will be thrown
                    var client = _clientFactory.CreateClient();
                    var response = await client.SendAsync(request);
                    if (!response.IsSuccessStatusCode)
                    {
                        logger.LogInformation($"E-mail sent to");
                    }

                    //as soon as a message is available, we'll send it
                    logger.LogInformation($"E-mail sent to");
                }
                catch (OperationCanceledException)
                {
                    //We need to terminate the delivery, so we'll just break the while loop
                    break;
                }
                catch
                {
#warning Implement a retry mechanism or else this message will be lost
                    logger.LogWarning($"Couldn't send an e-mail to");
                }
            }

            logger.LogInformation("E-mail background delivery stopped");
        }

        public void Dispose()
        {
            CancelSendTask();
        }
    }

и его часть для внедрения зависимостей

services.AddSingleton<SmSHandlerForCashBaba>();
services.AddSingleton<IHostedService>(serviceProvider => serviceProvider.GetService<SmSHandlerForCashBaba>());
            services.AddSingleton<ISmSHandlerForCashBaba>(serviceProvider => serviceProvider.GetService<SmSHandlerForCashBaba>());
...