Я работаю над многопоточным асинхронным приложением, которое отправляет массовые электронные письма.Я почти закончил приложение, но есть опасения по поводу производительности.Если вы ознакомите меня с лучшими лучшими практиками, это будет прекрасно, и я действительно изучу основы, поскольку я - младший разработчик.
Вот вопрос: во-первых, у меня есть кнопка «Пуск» для приложения, которое запускает Windows.Компонент Forms.Timer.
private void btnStart_MouseClick(object sender, MouseEventArgs e)
{
timerNewCampaignChecker.Tick += new EventHandler(timerNewCampaignChecker_Tick);
timerNewCampaignChecker.Enabled = true;
timerNewCampaignChecker.Start();
}
Приложению необходимо каждые 3 секунды проверять базу данных на наличие новых кампаний (1-й метод), настраивать сведения о кампании (2-й), встроенные в пользовательский ввод, и отправлять кампанию получателям черезэлектронная почта (3-й).Чтобы проверять базу данных каждые 3 секунды на наличие новых кампаний, у меня есть вышеуказанный таймер (интервал 3 секунды), который запускает поток, проверяя новые кампании:
MethodInvoker invoker;
private void timerNewCampaignChecker_Tick(object sender, EventArgs e)
{
invoker = new MethodInvoker(CheckNewCampaigns);
invoker.BeginInvoke(null, null);
}
Итак, таймер запускает метод CheckNewCampaigns в каждых 3секунд и пусть процесс начнется с первого шага. Правильно ли запускать поток и структуру ThreadPool из самого таймера ??? Теперь CheckNewCampaigns проверяет БД, создает объект List и для каждой кампании отправляет сведения об объекте другому методу с помощьювызывая ThreadPool.
delegate bool StepCaller(int campaignID);
private void CheckNewCampaigns()
{
StringBuilder builder = new StringBuilder();
StepCaller stepCaller = new StepCaller(PrepareCampaignEmail);
IEnumerable<Campaigns> CampaignsList = DatabaseManager.GetCampaignsList(DatabaseManager.GetNewCampaigns());
foreach (Campaigns Campaign in CampaignsList)
{
stepCaller.BeginInvoke(Campaign.CampaignID, new AsyncCallback(PrepareEmailCallback), null);
}
}
Должен ли я кодировать endInvoke в первом методе, или я должен просто запустить и забыть ?? .Поскольку наиболее важно то, что у приложения есть поток, параметры передаются между методами, 2-й метод должен знать, когда 1-й завершен, чтобы он мог взять campID и настроить его.Но при этом следует начинать новый поток и проверять новые кампании, что является 1-м методом.А также электронные письма должны быть отправлены в тот же момент.Новый метод (2-й) настраивает кампанию и вызывает другой метод (3-й) также с помощью ThreadPool.Вот оно:
private bool PrepareCampaignEmail(int campaignID)
{
EmailCaller emailCaller = new EmailCaller(SendEmail);
IEnumerable<Subscribers> SubscribersList = DatabaseManager.GetCampaignSubscribersList(DatabaseManager.GetCampaignSubscribers(campaignID));
CampaignCustomazition campaignCustomizer;
List<CampaignCustomazition> campaignCustomizedList = new List<CampaignCustomazition>(); // foreach in içindeki beginInvoke ı dışarıya çıkardığımda kullanılacak
foreach (Subscribers subscriber in SubscribersList)
{
campaignCustomizer = new CampaignCustomazition(campaignID);
campaignCustomizer.CustomizeSource(campaignID, out campaignCustomizer.source, out campaignCustomizer.format);
campaignCustomizer.CustomizeCampaignDetails(campaignID, out campaignCustomizer.subject, out campaignCustomizer.fromName, out campaignCustomizer.fromEmail, out campaignCustomizer.replyEmail);
campaignCustomizer.CustomizeSubscriberDetails(campaignID, out campaignCustomizer.subscriberID, out campaignCustomizer.email, out campaignCustomizer.fullName);
IAsyncResult result = emailCaller.BeginInvoke(campaignCustomizer, null, null);
try
{
emailCaller.EndInvoke(result);
}
catch(Exception ex)
{
Trace.WriteLine(ex.Message);
}
}
return false;
}
Я полагаю, что в этом втором шаге есть главная проблема. Операция с базой данных выполняется почти 5-6 раз.Это может быть проблемой для темы, может быть.Кажется, работает нормально, но мой путь может быть неправильным.Там могут быть десятки кампаний в один день.Это проблема или у меня все нормально? Операции с БД не такие уж жесткие и сложные.
После подготовки письма оно готово к отправке, которое вызывается выше.Третий метод - это простой метод SMTP, который отправляет электронную почту и регистрирует ее.
Этот последний метод также не имеет функции EndInvoke, но это последний метод приложения в качестве только что отправленной почты.
Вам логичен мой способ работы с таймером и ThreadPool ??Как я могу проверить производительность наилучшим образом и оптимизировать работу Threadpool?Что вы можете предложить и научить любому из вышеперечисленного?
Большое спасибо