2015-08-19 4 views
2

Im совершенно новый для потоковой передачи данных, и вы хотите использовать 6-процессорный процессор и улучшить его.Улучшения производительности и Threading ASP.Net MVC

Я пытаюсь найти несколько быстрых побед, мой маленький бизнес растет, и я заметил, что некоторые хиты производительности (несколько клиентов посоветовали мне) при заполнении нескольких разделов моей службы, некоторые из них Я предполагаю, вплоть до необходимости отправлять электронные письма и ждать ответа третьей стороны, является ли их простой способ передать это в другой поток \, не нарушая сеанс \ службу?

У меня есть действие, когда назначение «Завершено»

switch (appointment.State) 
{ 
case DomainObjects.AppointmentState.Completed: 
_clientService.SendMessageToClient(clientId,"Email title"EmailMessage(appointment, "AppointmentThankYou"), appointment.Id, userId); 
break; 
} 

Является ли это лучше?

case DomainObjects.AppointmentState.Completed: 
var emailThread = new Thread(() => _clientService.SendMessageToClient(clientId,"Email Subject", 
EmailMessage(appointment, "AppointmentThankYou"), 
appointment.Id, userId)) 
{ 
IsBackground = true 
}; 
emailThread.Start(); 

Конструктивная поддержка приветствуется.

ответ

2

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

Хотя существует несколько способов решения этой проблемы, одним из наиболее распространенных является использование очереди производителей-потребителей, предпочтительно с использованием поточной безопасной коллекции, такой как ConcurrentQueue, с количеством активных в течение длительного времени, например. отправка по электронной почте потоков в процессе в любое время, контролируемая механизмом синхронизации, например SemaphoreSlim

Я создал очень простое приложение для демонстрации этого подхода, как показано ниже. Ключевыми классами здесь являются

  1. Класс MessageProcessor, который поддерживает очередь и контролирует доступ как для добавления элементов метода AddToQueue, так и для отправки сообщений ReadFromQueue. Сам класс реализует Singleton pattern, чтобы в приложении присутствовал только один экземпляр (вам не нужны несколько очередей). Метод ReadFromQueue также реализует таймер (устанавливается на 2 секунды), который указывает, как часто задача должна быть создана для отправки сообщения.
  2. Класс SingletonBase просто абстрактный класс для реализации шаблона Singleton
  3. Класса MessageSender используется для реальной работы отправки сообщения
  4. Класс CreateMessagesForTest просто имитирует создание тестовых сообщений для целей этого ответа

Надеется, что это помогает

using System; 
    using System.Collections.Concurrent; 
    using System.Globalization; 
    using System.Reactive.Linq; 
    using System.Reflection; 
    using System.Threading; 
    using System.Threading.Tasks; 


    namespace ConsoleApplication9 
    { 
     internal class Program 
     { 

      private static void Main(string[] args) 
      { 

       MessagingProcessor.Instance.ReadFromQueue(); // starts the message sending tasks 

       var createMessages = new CreateMessagesForTest(); 
       createMessages.CreateTestMessages(); // creates sample test messages for processing 

       Console.ReadLine(); 

      } 


     } 

     /// <summary> 
     /// Simply creates test messages every second for sending 
     /// </summary> 
     public class CreateMessagesForTest 
     { 
      public void CreateTestMessages() 
      { 
       IObservable<long> observable = Observable.Interval(TimeSpan.FromSeconds(1)); 

       // Token for cancelation 
       var source = new CancellationTokenSource(); 

       // Create task to execute. 
       Action action = (CreateMessage); 

       // Subscribe the obserable to the task on execution. 
       observable.Subscribe(x => 
       { 
        var task = new Task(action); 
        task.Start(); 
       }, source.Token); 
      } 

      private static void CreateMessage() 
      { 
       var message = new Message {EMailAddress = "[email protected]", MessageBody = "abcdefg"}; 
       MessagingProcessor.Instance.AddToQueue(message); 
      } 
     } 



     /// <summary> 
     /// The conents of the email to send 
     /// </summary> 
     public class Message 
     { 
      public string EMailAddress { get; set; } 
      public string MessageBody { get; set; } 
     } 

     /// <summary> 
     /// Handles all aspects of processing the messages, only one instance of this class is allowed 
     /// at any time 
     /// </summary> 
     public class MessagingProcessor : SingletonBase<MessagingProcessor> 
     { 

      private MessagingProcessor() 
      { 
      } 


      private ConcurrentQueue<Message> _messagesQueue = new ConcurrentQueue<Message>(); 

      // create a semaphore to limit the number of threads which can send an email at any given time 
      // In this case only allow 2 to be processed at any given time 
      private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(2, 2); 

      public void AddToQueue(Message message) 
      { 
       _messagesQueue.Enqueue(message); 
      } 

      /// <summary> 
      /// Used to start the process for sending emails 
      /// </summary> 
      public void ReadFromQueue() 
      { 
       IObservable<long> observable = Observable.Interval(TimeSpan.FromSeconds(2)); 

       // Token for cancelation 
       var source = new CancellationTokenSource(); 

       // Create task to execute. 
       Action action = (SendMessages); 

       // Subscribe the obserable to the task on execution. 
       observable.Subscribe(x => 
       { 
        var task = new Task(action); 
        task.Start(); 
       }, source.Token); 


      } 

      /// <summary> 
      /// Handles dequeing and syncronisation to the queue 
      /// </summary> 
      public void SendMessages() 
      { 
       try 
       { 
        Semaphore.Wait(); 
        Message message; 
        while (_messagesQueue.TryDequeue(out message)) // if we have a message to send 
        { 
         var messageSender = new MessageSender(); 
         messageSender.SendMessage(message); 
        } 
       } 
       finally 
       { 
        Semaphore.Release(); 
       } 
      } 

     } 

     /// <summary> 
     /// Sends the emails 
     /// </summary> 
     public class MessageSender 
     { 
      public void SendMessage(Message message) 
      { 
       // do some long running task 
      } 
     } 

     /// <summary> 
     /// Implements singleton pattern on all classes which derive from it 
     /// </summary> 
     /// <typeparam name="T">Derived class</typeparam> 
     public abstract class SingletonBase<T> where T : class 
     { 

      public static T Instance 
      { 
       get { return SingletonFactory.Instance; } 
      } 

      /// <summary> 
      /// The singleton class factory to create the singleton instance. 
      /// </summary> 
      private class SingletonFactory 
      { 

       static SingletonFactory() 
       { 
       } 

       private SingletonFactory() 
       { 
       } 

       internal static readonly T Instance = GetInstance(); 

       private static T GetInstance() 
       { 
        var theType = typeof (T); 
        T inst; 
        try 
        { 
         inst = (T) theType 
          .InvokeMember(theType.Name, 
           BindingFlags.CreateInstance | BindingFlags.Instance 
           | BindingFlags.NonPublic, 
           null, null, null, 
           CultureInfo.InvariantCulture); 
        } 
        catch (MissingMethodException ex) 
        { 
         var exception = new TypeLoadException(string.Format(
          CultureInfo.CurrentCulture, 
          "The type '{0}' must have a private constructor to " + 
          "be used in the Singleton pattern.", theType.FullName) 
          , ex); 
         //LogManager.LogException(LogManager.EventIdInternal, exception, "error in instantiating the singleton"); 
         throw exception; 
        } 

        return inst; 
       } 
      } 
     } 
    } 
+0

Это не будет работать на приложениях ASP.NET в качестве темы может быть прервана в любой момент. – VMAtm

Смежные вопросы