C# 性能和线程改进ASP.NETMVC
我对线程技术完全陌生,希望利用6核处理器并获得改进 我试图找到一些快速的胜利,我的小生意正在增长,我注意到在完成我的服务的几个部分时出现了一些性能问题(一些客户建议我),我猜其中一些可能是因为需要发送电子邮件和等待第三方响应,在不中断会话\服务的情况下,他们是否可以轻松地将此消息传递到另一个线程\上 当约会“完成”时,我有一个操作 这样更好吗C# 性能和线程改进ASP.NETMVC,c#,asp.net-mvc,multithreading,C#,Asp.net Mvc,Multithreading,我对线程技术完全陌生,希望利用6核处理器并获得改进 我试图找到一些快速的胜利,我的小生意正在增长,我注意到在完成我的服务的几个部分时出现了一些性能问题(一些客户建议我),我猜其中一些可能是因为需要发送电子邮件和等待第三方响应,在不中断会话\服务的情况下,他们是否可以轻松地将此消息传递到另一个线程\上 当约会“完成”时,我有一个操作 这样更好吗 case DomainObjects.AppointmentState.Completed: var emailThread = new Thread(
case DomainObjects.AppointmentState.Completed:
var emailThread = new Thread(() => _clientService.SendMessageToClient(clientId,"Email Subject",
EmailMessage(appointment, "AppointmentThankYou"),
appointment.Id, userId))
{
IsBackground = true
};
emailThread.Start();
欢迎有建设性的反馈。老实说,我相信您上面概述的方法在投入生产之前需要大量的工作。想象一下,1000个用户点击你的网站——你现在有1000个后台任务,所有任务都试图同时发送消息。这可能会使您的系统在磁盘和网络IO方面出现瓶颈 虽然有许多方法可以解决此问题,但最常见的方法之一是使用生产者-消费者队列,最好使用线程安全的集合,例如使用活动长时间运行的线程数,例如,在由同步机制(如)控制的任何时间通过电子邮件发送进程中的线程 我创建了一个非常简单的应用程序来演示这种方法,如下所示。其中的关键类是
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 = "aa@aa.com", 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;
}
}
}
}
使用系统;
使用System.Collections.Concurrent;
利用制度全球化;
使用System.Reactive.Linq;
运用系统反思;
使用系统线程;
使用System.Threading.Tasks;
命名空间控制台应用程序9
{
内部课程计划
{
私有静态void Main(字符串[]args)
{
MessagingProcessor.Instance.ReadFromQueue();//启动消息发送任务
var createMessages=new CreateMessagesForTest();
createMessages.CreateTestMessages();//创建用于处理的示例测试消息
Console.ReadLine();
}
}
///
///只需每秒创建测试消息以发送
///
公共类CreateMessagesForTest
{
public void CreateTestMessages()
{
IObservable observable=可观测的时间间隔(时间跨度从秒(1));
//取消代币
var source=新的CancellationTokenSource();
//创建要执行的任务。
动作动作=(CreateMessage);
//在任务执行时订阅可观察内容。
可观察。订阅(x=>
{
var任务=新任务(操作);
task.Start();
},source.Token);
}
私有静态void CreateMessage()
{
var message=新邮件{EMailAddress=“aa@aa.com,MessageBody=“abcdefg”};
MessagingProcessor.Instance.AddToQueue(消息);
}
}
///
///要发送的电子邮件的内容
///
公共类消息
{
公共字符串电子邮件地址{get;set;}
公共字符串MessageBody{get;set;}
}
///
///处理处理消息的所有方面,只允许该类的一个实例
///随时
///
公共类MessagingProcessor:SingletonBase
{
专用消息处理器()
{
}
私有ConcurrentQueue_messagesQueue=新ConcurrentQueue();
//创建一个信号量来限制在任何给定时间可以发送电子邮件的线程数
//在这种情况下,在任何给定的时间只允许处理2
私有静态只读信号量slim信号量=新信号量slim(2,2);
公共无效AddToQueue(消息)
{
_messagesQueue.Enqueue(message);
}
///
///用于启动发送电子邮件的过程
///
public void ReadFromQueue()
{
IObservable-observable=可观测的时间间隔(TimeSpan.FromSeconds(2));
//取消代币
var source=新的CancellationTokenSource();
//创建要执行的任务。
动作动作=(发送消息);
//在任务执行时订阅可观察内容。
可观察。订阅(x=>
{
var任务=新任务(操作);
task.Start();
},source.Token);
}
///
///处理队列的解队列和同步
///
公共无效发送消息()
{
尝试
{
Semaphore.Wait();
信息;
while(_messagesque.TryDequeue(out message))//如果我们有消息要发送
{
var messageSender=new messageSender()
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 = "aa@aa.com", 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;
}
}
}
}