Gmail Календарь Документы Reader Веб ещё »
Недавно посещенные группы | Справка | Вход
Главная страница Google Groups
Jon Skeet's ProducerConsumer
В данный момент в этой группе слишком много тем, которые должны показываться в первую очередь. Чтобы эта тема показывалась в первую очередь, измените этот параметр для какой-то другой темы.
При обработке Вашего запроса произошла ошибка. Повторите попытку.
пометка
  Сообщений: 8 - Свернуть все  -  Перевести все на Переведено (просмотреть все оригиналы)
Сообщение будет отправлено в группу Usenet. Когда Вы отправляете сообщения в такие группы, Ваш адрес электронной почты публикуется в Интернете.
Ваш ответ не был отправлен.
Сообщение отправлено успешно.
 
Автор:
Кому:
Копия:
В ответ на:
Добавить копию | Добавить заголовок "В ответ на" | Изменить тему
Тема:
Утверждение:
Для подтверждения введите символы, изображенные на картинке ниже, или цифры, которые вы услышите, нажав на значок упрощенного доступа. Слушайте и вводите услышанные числа
 
Cool Guy  
Просмотреть профиль   Перевести на Переведено (просмотреть оригинал)
 Дополнительные параметры 25 май 2005, 21:01
Группы новостей: microsoft.public.dotnet.framework
Автор: Cool Guy <cool...@abc.xyz>
Дата: Wed, 25 May 2005 18:01:45 +0100
Местное время: Ср. 25 май 2005 21:01
Тема: Jon Skeet's ProducerConsumer
I'm using a ProducerConsumer in a worker thread.  If I want to end this
thread, and it's currently waiting for Consumer to return, what's the best
way to proceed?

Should I just make the thread a background thread?  Or should I pass a
dummy object to ProducerConsumer.Produce to make Consume return?  Or is
there a better way?

| public class ProducerConsumer
| {
|     readonly object listLock = new object();
|     Queue queue = new Queue();
|
|     public void Produce(object o)
|     {
|         lock (listLock)
|         {
|             queue.Enqueue(o);
|             if (queue.Count==1)
|             {
|                 Monitor.Pulse(listLock);
|             }
|         }
|     }
|    
|     public object Consume()
|     {
|         lock (listLock)
|         {
|             while (queue.Count==0)
|             {
|                 Monitor.Wait(listLock);
|             }
|             return queue.Dequeue();
|         }
|     }
| }


    Переслать  
Чтобы отправлять сообщения, сначала необходимо Войти.
Чтобы отправлять сообщения, сначала необходимо присоединиться к группе.
Перед отправкой сообщения обновите свой псевдоним на странице Настройки подписки.
У вас нет разрешения на отправку сообщений.
Jon Skeet [ C# MVP ]  
Просмотреть профиль   Перевести на Переведено (просмотреть оригинал)
 Дополнительные параметры 25 май 2005, 21:10
Группы новостей: microsoft.public.dotnet.framework
Автор: Jon Skeet [C# MVP] <sk...@pobox.com>
Дата: Wed, 25 May 2005 18:10:05 +0100
Местное время: Ср. 25 май 2005 21:10
Тема: Re: Jon Skeet's ProducerConsumer

Cool Guy <cool...@abc.xyz> wrote:
> I'm using a ProducerConsumer in a worker thread.  If I want to end this
> thread, and it's currently waiting for Consumer to return, what's the best
> way to proceed?

> Should I just make the thread a background thread?  Or should I pass a
> dummy object to ProducerConsumer.Produce to make Consume return?  Or is
> there a better way?

You could put a flag in the class to say "I'm stopping" and have a Stop
method which sets the flag and pulses the monitor. The Consume method
should then check the flag before dequeuing anything (or waiting).

--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


    Переслать  
Чтобы отправлять сообщения, сначала необходимо Войти.
Чтобы отправлять сообщения, сначала необходимо присоединиться к группе.
Перед отправкой сообщения обновите свой псевдоним на странице Настройки подписки.
У вас нет разрешения на отправку сообщений.
Cool Guy  
Просмотреть профиль   Перевести на Переведено (просмотреть оригинал)
 Дополнительные параметры 25 май 2005, 21:51
Группы новостей: microsoft.public.dotnet.framework
Автор: Cool Guy <cool...@abc.xyz>
Дата: Wed, 25 May 2005 18:51:58 +0100
Местное время: Ср. 25 май 2005 21:51
Тема: Re: Jon Skeet's ProducerConsumer
"Jon Skeet [C# MVP]" <sk...@pobox.com> wrote:

> You could put a flag in the class to say "I'm stopping" and have a Stop
> method which sets the flag and pulses the monitor. The Consume method
> should then check the flag before dequeuing anything (or waiting).

Something like this (added lines are prepended with '+', and removed lines
with '-')?

 public class ProducerConsumer
 {
     readonly object listLock = new object();
     Queue queue = new Queue();
+    volatile bool stopped = false;

     public void Produce(object o)
     {
         lock (listLock)
         {
             queue.Enqueue(o);
             if (queue.Count==1)
             {
                 Monitor.Pulse(listLock);
             }
         }
     }

     public object Consume()
     {
         lock (listLock)
         {
-            while (queue.Count==0)
+            while (queue.Count==0 && !stopped)
             {
                 Monitor.Wait(listLock);
             }
-            return queue.Dequeue();
+            return stopped ? null : queue.Dequeue();
         }
     }

+    public void Stop()
+    {
+        stopped = true;
+        Monitor.Pulse(listLock);
+    }
 }

I believe that making stopped *volatile* should make it thread-safe here..?


    Переслать  
Чтобы отправлять сообщения, сначала необходимо Войти.
Чтобы отправлять сообщения, сначала необходимо присоединиться к группе.
Перед отправкой сообщения обновите свой псевдоним на странице Настройки подписки.
У вас нет разрешения на отправку сообщений.
Jon Skeet [ C# MVP ]  
Просмотреть профиль   Перевести на Переведено (просмотреть оригинал)
 Дополнительные параметры 25 май 2005, 22:17
Группы новостей: microsoft.public.dotnet.framework
Автор: Jon Skeet [C# MVP] <sk...@pobox.com>
Дата: Wed, 25 May 2005 19:17:29 +0100
Местное время: Ср. 25 май 2005 22:17
Тема: Re: Jon Skeet's ProducerConsumer

Cool Guy <cool...@abc.xyz> wrote:
> "Jon Skeet [C# MVP]" <sk...@pobox.com> wrote:

> > You could put a flag in the class to say "I'm stopping" and have a Stop
> > method which sets the flag and pulses the monitor. The Consume method
> > should then check the flag before dequeuing anything (or waiting).

> Something like this (added lines are prepended with '+', and removed lines
> with '-')?

Yup, that looks okay. Personally I don't like using volatile,
preferring a property which takes care of the thread-safety, but that
would certainly work and would be thread-safe.

You'd need to make sure the consumer knew that null meant "the queue
might have stopped" of course. (You would probably want to expose the
stopped flag as a public property too, just in case you ever wanted to
*actually* produce a null.)

--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


    Переслать  
Чтобы отправлять сообщения, сначала необходимо Войти.
Чтобы отправлять сообщения, сначала необходимо присоединиться к группе.
Перед отправкой сообщения обновите свой псевдоним на странице Настройки подписки.
У вас нет разрешения на отправку сообщений.
Cool Guy  
Просмотреть профиль   Перевести на Переведено (просмотреть оригинал)
 Дополнительные параметры 25 май 2005, 22:42
Группы новостей: microsoft.public.dotnet.framework
Автор: Cool Guy <cool...@abc.xyz>
Дата: Wed, 25 May 2005 19:42:43 +0100
Местное время: Ср. 25 май 2005 22:42
Тема: Re: Jon Skeet's ProducerConsumer
"Jon Skeet [C# MVP]" <sk...@pobox.com> wrote:

> Yup, that looks okay.

Right.

> Personally I don't like using volatile,
> preferring a property which takes care of the thread-safety, but that
> would certainly work and would be thread-safe.

Right.

> You'd need to make sure the consumer knew that null meant "the queue
> might have stopped" of course. (You would probably want to expose the
> stopped flag as a public property too, just in case you ever wanted to
> *actually* produce a null.)

Right.

Thanks for your help!


    Переслать  
Чтобы отправлять сообщения, сначала необходимо Войти.
Чтобы отправлять сообщения, сначала необходимо присоединиться к группе.
Перед отправкой сообщения обновите свой псевдоним на странице Настройки подписки.
У вас нет разрешения на отправку сообщений.
Cool Guy  
Просмотреть профиль   Перевести на Переведено (просмотреть оригинал)
 Дополнительные параметры 26 май 2005, 01:13
Группы новостей: microsoft.public.dotnet.framework
Автор: Cool Guy <cool...@abc.xyz>
Дата: Wed, 25 May 2005 22:13:21 +0100
Местное время: Чт. 26 май 2005 01:13
Тема: Re: Jon Skeet's ProducerConsumer

I wrote:
> Something like this (added lines are prepended with '+', and removed lines
> with '-')?

[snip]

Argh!  I can't get it to work!

I get an exception when I try to call ProducerConsumer.Stop:

    An unhandled exception of type
    'System.Threading.SynchronizationLockException' occurred in
    mscorlib.dll

    Additional information: Object synchronization method was called from
    an unsynchronized block of code.

I can't see how to get around this.

Full code:

using System;
using System.Collections;
using System.Threading;

public class Test
{
    static ProducerConsumer queue = new ProducerConsumer();

    static void Main()
    {
        new Thread(new ThreadStart(ConsumerJob)).Start();

        queue.Produce(new object());
        Thread.Sleep(2000);
        queue.Stop();
    }

    static void ConsumerJob()
    {
        while (!queue.Stopped)
        {
            object o = queue.Consume();
            Console.WriteLine("Consuming {0}.", o);
        }
    }

}

public class ProducerConsumer
{
    readonly object listLock = new object();
    Queue queue = new Queue();
    volatile bool stopped = false;

    public bool Stopped
    {
        get { return stopped; }
    }

    public void Produce(object o)
    {
        lock (listLock)
        {
            queue.Enqueue(o);
            if (queue.Count==1)
            {
                Monitor.Pulse(listLock);
            }
        }
    }

    public object Consume()
    {
        lock (listLock)
        {
            while (queue.Count==0 && !stopped)
            {
                Monitor.Wait(listLock);
            }
            return stopped ? null : queue.Dequeue();
        }
    }

    public void Stop()
    {
        stopped = true;
        Monitor.Pulse(listLock);
    }


    Переслать  
Чтобы отправлять сообщения, сначала необходимо Войти.
Чтобы отправлять сообщения, сначала необходимо присоединиться к группе.
Перед отправкой сообщения обновите свой псевдоним на странице Настройки подписки.
У вас нет разрешения на отправку сообщений.
Jon Skeet [ C# MVP ]  
Просмотреть профиль   Перевести на Переведено (просмотреть оригинал)
 Дополнительные параметры 26 май 2005, 02:23
Группы новостей: microsoft.public.dotnet.framework
Автор: Jon Skeet [C# MVP] <sk...@pobox.com>
Дата: Wed, 25 May 2005 23:23:13 +0100
Местное время: Чт. 26 май 2005 02:23
Тема: Re: Jon Skeet's ProducerConsumer

Cool Guy <cool...@abc.xyz> wrote:
> I wrote:

> > Something like this (added lines are prepended with '+', and removed lines
> > with '-')?

> [snip]

> Argh!  I can't get it to work!

> I get an exception when I try to call ProducerConsumer.Stop:

You're calling Monitor.Pulse on listLock without acquiring the monitor
first. Change it to:

lock (listLock)
{
    Monitor.Pulse (listLock);

}

and it should be fine.

--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


    Переслать  
Чтобы отправлять сообщения, сначала необходимо Войти.
Чтобы отправлять сообщения, сначала необходимо присоединиться к группе.
Перед отправкой сообщения обновите свой псевдоним на странице Настройки подписки.
У вас нет разрешения на отправку сообщений.
Cool Guy  
Просмотреть профиль   Перевести на Переведено (просмотреть оригинал)
 Дополнительные параметры 26 май 2005, 02:36
Группы новостей: microsoft.public.dotnet.framework
Автор: Cool Guy <cool...@abc.xyz>
Дата: Wed, 25 May 2005 23:36:42 +0100
Местное время: Чт. 26 май 2005 02:36
Тема: Re: Jon Skeet's ProducerConsumer
"Jon Skeet [C# MVP]" <sk...@pobox.com> wrote:

> You're calling Monitor.Pulse on listLock without acquiring the monitor
> first.

Aha!

    Переслать  
Чтобы отправлять сообщения, сначала необходимо Войти.
Чтобы отправлять сообщения, сначала необходимо присоединиться к группе.
Перед отправкой сообщения обновите свой псевдоним на странице Настройки подписки.
У вас нет разрешения на отправку сообщений.
Конец сообщений
« Назад к обсуждениям « Следующая тема     Предыдущая тема »

Создать группу - Группы Google - Главная страница Google - Условия предоставления услуг - Политика конфиденциальности
©2010 Google