Многопоточность: WaitAll не ждет, как ожидалось - PullRequest
0 голосов
/ 19 февраля 2011

У меня есть поток, который вызывает две отдельные темы, чтобы сделать какую-то работу. Всякий раз, когда какое-либо из заданий завершается, вызывается Waithandle.Set (0, и в конце родительского рабочего потока я хотел, чтобы WaitAll завершил оба, прежде чем я продолжу. Но priceA () все еще появляется первым, а затем PriceB ().

new Thread(() =>
                           {
                               new Thread(() =>
                               {
                                   PriceA = _service.GetPriceA();
                                   _waithandle[0].Set();
                               }).Start();

                               new Thread(() =>
                               {
                                   PriceB = _service.GetPriceB();
                                   _waithandle[1].Set();
                               }).Start();

                               WaitHandle.WaitAll(_waithandle);
                           }).Start();
Console.WriteLine("Hello");

Чего мне не хватает?

Обновление:

private EventWaitHandle[] _waithandle;

CTOR:

 _waithandle[0] = new ManualResetEvent(false);
 _waithandle[1] = new ManualResetEvent(false);

Ответы [ 3 ]

4 голосов
/ 19 февраля 2011

Вы создаете отдельный поток для ожидания ... но код после оператора, который вы дали, будет продолжаться, потому что вы не ожидаете в этом потоке.Другими словами, вы создаете три потока:

  • Поток X: создает потоки A и B, затем ожидает их завершения
  • Поток A: получает PriceA и затем устанавливает waitHandle[0]
  • Поток B: получает PriceB и затем устанавливает waitHandle [1]

Но поток X ничего не делает после он ожидает, так какой смысложидания внутри него?

Кроме того, было бы намного проще просто вызвать Join на дополнительных потоках, которые вы создали.На самом деле, если вам нужно только подождать в «текущем» потоке, вам нужен только один дополнительный поток в первую очередь:

Thread t = new Thread(() => { PriceA = _service.GetPriceA(); });
t.Start();
PriceB = _service.GetPriceB();
t.Join();
// Other code

к тому времени, когда вы достигнете другого кода", PriceA и PriceB будут установлены.Конечно, в нем отсутствует значительная часть обработки ошибок ... но это легче добавить, когда у вас есть более простая отправная точка, чем ваш в настоящее время слишком сложный код.

0 голосов
/ 19 февраля 2011
new Thread(() =>
                           {
                               new Thread(() =>
                               {
                                   _priceA = _service.GetPriceA();
                                   _waithandle[0].Set();
                               }).Start();

                               new Thread(() =>
                               {
                                   _priceB = _service.GetPriceB();
                                   _waithandle[1].Set();
                               }).Start();

                               WaitHandle.WaitAll(_waithandle);
                               PriceA = _priceA;
                               PriceB = _priceB;
                           }).Start();

Это сделало работу за меня. Culprit был INotifyChangedProperty () PriceA и PriceB, который слишком рано обновлял пользовательский интерфейс, делая мою избыточную стойку ожидания. В случае, если у кого-то еще есть подобная проблема ...

0 голосов
/ 19 февраля 2011

Правильно ли вы сбрасываете значения _waithandle[0] и [1]?Например:

_waithandle[0] = new ManualResetEvent(false);
_waithandle[1] = new ManualResetEvent(false);
...