попробуйте это:
<audio controls autoplay>
<src="/home/user/public_html/copyrighted-music.mp3" hidden autoplay>
<embed src="/home/user/public_html/copyrighted-music.mp3" width="180" height="90" hidden="true">
</audio>
Используйте очередь в качестве конечного буфера, обработанного его собственным потоком.
Назовите метод очереди заливки для создания очереди электронных писем, ограниченных, чтобы (сказать) 10. Заполните его первыми 10 неотправленными электронными письмами. Запустите поток, чтобы обработать очередь - для каждой электронной почты в очереди, отправить его асинхронный. Когда очередь является пустым сном некоторое время и проверкой снова. Имейте делегата завершения, удаляют посланное или электронное письмо с ошибками из очереди и обновляют базу данных, затем называют метод очереди заливки для чтения более неотправленных электронных писем в очередь (назад до предела).
Вы будете только нуждаться в блокировках вокруг работ с очередями и должны будете только управлять (непосредственно) одним потоком для обработки очереди. У Вас никогда не будет больше, чем потоки N+1 активный сразу, где N является пределом очереди.
Я полагаю, что Ваше hacky решение на самом деле работало бы. Просто удостоверьтесь, что у Вас есть оператор блокировки вокруг битов, где Вы увеличиваете и постепенно уменьшаете счетчик:
class EmailSender
{
object SimultaneousEmailsLock;
int SimultaneousEmails;
public string[] Recipients;
void SendAll()
{
foreach(string Recipient in Recipients)
{
while (SimultaneousEmails>10) Thread.Sleep(10);
SendAnEmail(Recipient);
}
}
void SendAnEmail(string Recipient)
{
lock(SimultaneousEmailsLock)
{
SimultaneousEmails++;
}
... send it ...
}
void FinishedEmailCallback()
{
lock(SimultaneousEmailsLock)
{
SimultaneousEmails--;
}
... etc ...
}
}
Я добавил бы все свои сообщения к Очереди и затем метал бы икру т.е. 10 потоков, которые послали электронные письма, пока Очередь не была пуста. Pseudo'ish C# (вероятно, компиляция привычки):
class EmailSender
{
Queue<Message> messages;
List<Thread> threads;
public Send(IEnumerable<Message> messages, int threads)
{
this.messages = new Queue<Message>(messages);
this.threads = new List<Thread>();
while(threads-- > 0)
threads.Add(new Thread(SendMessages));
threads.ForEach(t => t.Start());
while(threads.Any(t => t.IsAlive))
Thread.Sleep(50);
}
private SendMessages()
{
while(true)
{
Message m;
lock(messages)
{
try
{
m = messages.Dequeue();
}
catch(InvalidOperationException)
{
// No more messages
return;
}
}
// Send message in some way. Not in an async way,
// since we are already kind of async.
Thread.Sleep(); // Perhaps take a quick rest
}
}
}
Если сообщение является тем же, и просто имеющий многих получателей, просто подкачайте сообщение с Получателем и добавьте единственный параметр сообщения к Отправить методу.
Не это что-то это Thread.Sleep()
может обработать?
Вы корректны в размышлении, что фоновая поточная обработка может служить хорошей цели здесь. В основном то, что Вы хотите сделать, создают фоновый поток для этого процесса, позволяет ему выполнить свой собственный путь, задержки и все, и затем завершить поток когда процесс сделан, или оставляют его на неограниченно долго (превращающий его в службу Windows или что-то подобное будет хорошая идея).
Немного введения на многопоточности может быть считано здесь (с Потоком. Сон включен!).
Хорошее введение на Windows Services может быть считано здесь.
Вы могли использовать Таймер.NET для установки расписания для отправки сообщений. Каждый раз, когда таймер стреляет, захватите следующие 10 сообщений и отправьте их всех и повторение. Или если Вы хотите генерала (10 сообщений в секунду) уровень, у Вас мог бы быть таймер, запускают каждые 100 мс и отправляют единственному сообщению каждый раз.
При необходимости в более усовершенствованном планировании Вы могли бы посмотреть на платформу планирования как Quartz.NET