Мне нравится предложение usr относительно использования потока данных TPL. Если у вас есть возможность добавлять внешние зависимости к вашему проекту (поток данных TPL не распространяется как часть платформы .NET), то он обеспечивает чистое решение вашей проблемы.
Если вы придерживаетесь того, что предлагает инфраструктура, вы должны взглянуть на BlockingCollection<T>
, который прекрасно работает с шаблоном производителя-потребителя, который вы пытаетесь реализовать.
Я собрал быстрый пример .NET 4.0, чтобы проиллюстрировать, как его можно использовать в вашем сценарии. Он не очень тощий, потому что у него много звонков Console.WriteLine()
. Однако, если вы вынимаете весь беспорядок, это очень просто.
В центре этого является BlockingCollection<Action>
, который получает Action
делегатов добавили к нему из любого потока, и поток специально предназначенный для выполнения, и извлечения из очереди тех, Action
сек последовательно в том порядке, в котором они были добавлены.
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace SimpleProducerConsumer
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main thread id is {0}.", Thread.CurrentThread.ManagedThreadId);
using (var blockingCollection = new BlockingCollection<Action>())
{
// Start our processing loop.
var actionLoop = new Thread(() =>
{
Console.WriteLine(
"Starting action loop on thread {0} (dedicated action loop thread).",
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsThreadPoolThread);
// Dequeue actions as they become available.
foreach (var action in blockingCollection.GetConsumingEnumerable())
{
// Invoke the action synchronously
// on the "actionLoop" thread.
action();
}
Console.WriteLine("Action loop terminating.");
});
actionLoop.Start();
// Enqueue some work.
Console.WriteLine("Enqueueing action 1 from thread {0} (main thread).", Thread.CurrentThread.ManagedThreadId);
blockingCollection.Add(() => SimulateWork(1));
Console.WriteLine("Enqueueing action 2 from thread {0} (main thread).", Thread.CurrentThread.ManagedThreadId);
blockingCollection.Add(() => SimulateWork(2));
// Let's enqueue it from another thread just for fun.
var enqueueTask = Task.Factory.StartNew(() =>
{
Console.WriteLine(
"Enqueueing action 3 from thread {0} (task executing on a thread pool thread).",
Thread.CurrentThread.ManagedThreadId);
blockingCollection.Add(() => SimulateWork(3));
});
// We have to wait for the task to complete
// because otherwise we'll end up calling
// CompleteAdding before our background task
// has had the chance to enqueue action #3.
enqueueTask.Wait();
// Tell our loop (and, consequently, the "actionLoop" thread)
// to terminate when it's done processing pending actions.
blockingCollection.CompleteAdding();
Console.WriteLine("Done enqueueing work. Waiting for the loop to complete.");
// Block until the "actionLoop" thread terminates.
actionLoop.Join();
Console.WriteLine("Done. Press Enter to quit.");
Console.ReadLine();
}
}
private static void SimulateWork(int actionNo)
{
Thread.Sleep(500);
Console.WriteLine("Finished processing action {0} on thread {1} (dedicated action loop thread).", actionNo, Thread.CurrentThread.ManagedThreadId);
}
}
}
И выход:
0.016s: Main thread id is 10.
0.025s: Enqueueing action 1 from thread 10 (main thread).
0.026s: Enqueueing action 2 from thread 10 (main thread).
0.027s: Starting action loop on thread 11 (dedicated action loop thread).
0.028s: Enqueueing action 3 from thread 6 (task executing on a thread pool thread).
0.028s: Done enqueueing work. Waiting for the loop to complete.
0.527s: Finished processing action 1 on thread 11 (dedicated action loop thread).
1.028s: Finished processing action 2 on thread 11 (dedicated action loop thread).
1.529s: Finished processing action 3 on thread 11 (dedicated action loop thread).
1.530s: Action loop terminating.
1.532s: Done. Press Enter to quit.
Вы эффективно не можете использовать Thread.Abort. Найдите на SO, чтобы найти некоторые дискуссии о том, почему. – usr
Вы действительно хотите сделать это в ASP.NET? Это похоже на то, что работает на сервере и работает независимо от клиентских браузеров. –
@usr Ok. Спасибо за ваш совет. – My2ndLovE