Ожидание завершения фонового потока - PullRequest
5 голосов
/ 24 октября 2011

Извините, если это дубликат, но я не совсем уверен, какие термины мне нужно использовать, чтобы найти существующие ответы на этот вопрос.

Я пытаюсь улучшить производительность запуска приложения, псевдокод выглядит примерно так.

LoadBigFileFromDisk();  //slow
SetupNetwork();         //even slower
UseBigFileFromDisk();

Я подумал, что, поскольку первый шаг связан с диском, а другой - с сетью (и медленнее), я мог бы запустить первый в фоновом потоке (в настоящее время играет с ThreadPool.QueueUserWorkItem, но не уверен, что это лучший кстати) и немного улучшить производительность.

Это работает, но меня беспокоит то, что я полагаюсь на то, что второй шаг достаточно медленный, чтобы завершить первый.

Я знаю, что мог бы установить где-нибудь логическое значение _done и while !, но есть ли более элегантное / идиоматическое решение?

(пока не .Net 4.0, поэтому, хотя я заинтересован в задачах, мне нужны запасные решения).

Ответы [ 3 ]

3 голосов
/ 24 октября 2011

В «основном классе» сделайте это:

ManualResetEvent mre = new ManualResetEvent(false);

в вашем "основном" методе сделайте это:

// Launch the tasks

mre.WaitOne();

в задании, когда оно заканчивается (непосредственно перед возвратом :-))

mre.Set();

Если вам нужно дождаться нескольких событий, в вашем «главном» создайте несколько ManualResetEvent и поместите их в массив, каждое событие «подключается» к одной из задач, а затем каждая задача Set получает свое событие. когда это закончится. Тогда в своей «основной» вы делаете:

WaitHandle.WaitAll(arrayOfManualResetEvents);

Обратите внимание, что таким образом вы можете подождать до 64 событий. Если вам нужно больше, есть другой метод (и обратите внимание, что вы должны использовать этот последний метод, даже если вы находитесь в потоке STA, например, в главном потоке приложения WinForm).

ManualResetEvent mre = new ManualResetEvent(false);
int remaining = xxx; // Number of "tasks" that must be executed.

// Launch tasks

mre.WaitOne();

В конце каждого задания

if (Interlocked.Decrement(ref remaining) == 0)
{
    mre.Set();
}

Только последнее задание уменьшит оставшееся поле до 0 и mre.Set().

3 голосов
/ 24 октября 2011

Вы можете попробовать:

var loadTask=Task.Factory.StartNew(()=>LoadBigFileFromDisk());
var setupTask=Task.Factory.StartNew(()=>SetupNetwork());

Task.WaitAll(loadTask,setupTask);

UseBigFileFromDisk();

Используется библиотека параллельных задач.

или

var loadThread=new Thread(()=>LoadBigFileFromDisk());
var setupThread=new Thread(()=>SetupNetwork());

loadThread.Start();
setupThread.Start();

loadThread.Join();
setupThread.Join();

UseBigFileFromDisk();

Когда вы не используете .NET 4. Если выполнение этих задач занимает много времени, лучше избегать пула потоков, так как это в основном для краткосрочных задач.

0 голосов
/ 24 октября 2011

Попробуйте Thread.Join. Что-то вроде networkThread.Join()

http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...