Допустим, у меня есть бизнес-объект, создание которого очень дорого, и я бы никогда не хотел создавать в своем приложении более 10 экземпляров этого объекта.Таким образом, это означало бы, что я бы никогда не хотел, чтобы одновременно выполнялось более 10 рабочих потоков.
Я бы хотел использовать новые System.Threading.Tasks для создания задачи, подобной этой:
var task = Task.Factory.StartNew(() => myPrivateObject.DoSomethingProductive());
Существует ли пример, показывающий, как:
- создать «пул объектов» для использования в TaskFactory?
- ограничить TaskFactory указанным числом потоков?
- заблокировать экземпляр в пуле объектов, чтобы он мог использоваться только одной задачей за раз?
Ответ Игби привел меня к этому отличному сообщению в блоге от Джастина Этериджа.который затем побудил меня написать этот пример:
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
namespace MyThreadedApplication
{
class Program
{
static void Main(string[] args)
{
// build a list of 10 expensive working object instances
var expensiveStuff = new BlockingCollection<ExpensiveWorkObject>();
for (int i = 65; i < 75; i++)
{
expensiveStuff.Add(new ExpensiveWorkObject(Convert.ToChar(i)));
}
Console.WriteLine("{0} expensive objects created", expensiveStuff.Count);
// build a list of work to be performed
Random r = new Random();
var work = new ConcurrentQueue<int>();
for (int i = 0; i < 1000; i++)
{
work.Enqueue(r.Next(10000));
}
Console.WriteLine("{0} items in work queue", work.Count);
// process the list of work items in fifteen threads
for (int i = 1; i < 15; i++)
{
Task.Factory.StartNew(() =>
{
while (true)
{
var expensiveThing = expensiveStuff.Take();
try
{
int workValue;
if (work.TryDequeue(out workValue))
{
expensiveThing.DoWork(workValue);
}
}
finally
{
expensiveStuff.Add(expensiveThing);
}
}
});
}
}
}
}
class ExpensiveWorkObject
{
char identity;
public void DoWork(int someDelay)
{
System.Threading.Thread.Sleep(someDelay);
Console.WriteLine("{0}: {1}", identity, someDelay);
}
public ExpensiveWorkObject(char Identifier)
{
identity = Identifier;
}
}
Итак, я использую BlockingCollection в качестве пула объектов, и рабочие потоки не проверяют очередь на доступную работу, пока не получат эксклюзивный элемент управлениянад одним из дорогих экземпляров объекта.Я думаю это отвечает моим требованиям, но мне бы очень хотелось получить отзывы от людей, которые знают это лучше, чем я ...