попробуйте этот код:
CultureInfo french = CultureInfo.GetCultureInfo("fr-FR");
CultureInfo arabic = CultureInfo.GetCultureInfo("ar-AR");
String nowStr = DateTime.Now.ToString(french);
string dt = DateTime.Parse(nowStr, french).ToString(arabic);
Console.WriteLine(" DATE : " + nowStr.ToString());
Console.WriteLine(" DATE : " + dt.ToString());
Console.Read();
Даже если другие ответы хороши если вам нужен другой вариант (у вас никогда не будет достаточно вариантов), то как об этом в качестве идеи.
Просто поместите данные для каждого задания в структуру, которая находится в стеке FIFO.
Создайте 15 потоков.
Каждый поток получит следующее задание из стека, отбрасывая его.
Когда поток завершает обработку, получает следующее задание, если стек пуст, поток умирает или просто спит, ожидая.
Единственная сложность, которую довольно просто решить,всплывающее окно находится в критическом разделе (синхронизировать чтение / всплывающее окно).
Re: «как-то дождаться их завершения»
ManualResetEvent - ваш друг, прежде чем вы начнете свою большую партию, создайте одного из этих щенков, ожидайте его в главном потоке, установите его в конце фоновой операции, когда работа будет завершена.
Другой вариант - вручную создать потоки и создать поток foreach, thread.Join ()
Вы можете использовать это (я использую это во время тестирования)
private void Repeat(int times, int asyncThreads, Action action, Action done) {
if (asyncThreads > 0) {
var threads = new List<Thread>();
for (int i = 0; i < asyncThreads; i++) {
int iterations = times / asyncThreads;
if (i == 0) {
iterations += times % asyncThreads;
}
Thread thread = new Thread(new ThreadStart(() => Repeat(iterations, 0, action, null)));
thread.Start();
threads.Add(thread);
}
foreach (var thread in threads) {
thread.Join();
}
} else {
for (int i = 0; i < times; i++) {
action();
}
}
if (done != null) {
done();
}
}
Использование:
// Do something 100 times in 15 background threads, wait for them all to finish.
Repeat(100, 15, DoSomething, null)
Когда вы ставите рабочий элемент в очередь потока, вы должны получить ручку ожидания обратно. Поместите их все в массив, и вы можете передать его в качестве аргумента функции WaitAll ()
.
Я бы просто использовал Task Parallel Library.
Вы можете сделать это как один простой цикл Parallel.For с вашими задачами, и он автоматически справится с этим довольно чисто. Если вы не можете дождаться C # 4 и реализации Microsoft, временный обходной путь - просто скомпилировать и использовать Mono-реализацию TPL . (Я лично предпочитаю реализацию MS, особенно более новые бета-версии, но Mono-версия является функциональной и распространяемой сегодня.)
Я бы использовал ThreadPool.
Перед тем, как начать работу, создайте ManualResetEvent и счетчик int. Добавьте каждое задание в ThreadPool, увеличивая счетчик каждый раз.
В конце каждого задания уменьшайте счетчик и, когда он достигает нуля, вызовите Set () для события.
В ваш главный поток, вызовите WaitOne () , чтобы дождаться завершения всех заданий.
ThreadPool
может быть подходящим вариантом. Метод SetMaxThreads
сможет ограничить количество выполняемых потоков. Однако это ограничивает максимальное количество потоков для процесса / домена приложений. Я бы не советовал использовать SetMaxThreads
, если процесс запущен как служба.
private static ManualResetEvent manual = new ManualResetEvent(false);
private static int count = 0;
public void RunJobs( List<JobState> states )
{
ThreadPool.SetMaxThreads( 15, 15 );
foreach( var state in states )
{
Interlocked.Increment( count );
ThreadPool.QueueUserWorkItem( Job, state );
}
manual.WaitOne();
}
private static void Job( object state )
{
// run job
Interlocked.Decrement( count );
if( Interlocked.Read( count ) == 0 ) manual.Set();
}
Вот псевдокод того, как я бы подошел (это не использует ThreadPool, так что кто-то может получим лучший ответ:)
main
{
create queue of 100 jobs
create new array of 15 threads
start threads, passing each the job queue
do whatever until threads are done
}
thread(queue)
{
while(queue isn't empty)
{
lock(queue) { if queue still isn't empty dequeue a thing }
process the thing
}
queue is empty so exit thread
}
РЕДАКТИРОВАТЬ: Если ваша проблема заключается в том, как определить, когда потоки завершены, и вы используете обычные потоки C # (не потоки ThreadPooled), вы можете вызывать Thread.Join () для каждого потока с помощью необязательный таймаут, и он вернется только после завершения потока. Если вы хотите следить за тем, сколько потоков сделано, не зацикливаясь на одном, вы можете циклически просматривать их следующим образом:
for(int i = 0; allThreads.Count > 0; i++)
{
var thisThread = allThreads[i % threads.Count];
if(thisThread.Join(timeout)) // something low, maybe 100 ms or something
allThreads.Remove(thisThread);
}