Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопрос по синхронизации 
V
    Опции темы
Red Wind
Дата 1.7.2007, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 280
Регистрация: 25.6.2004
Где: Минск

Репутация: нет
Всего: 2



Скажите как можно сделать так, что бы когда у меня уже создан экземпляр определённого класса, при попытке создания экземпляра этого класса в другом потоке этот поток ждал пока первый экземпляр класса не будет разружен. Спасибо за вниманиеsmile
PM MAIL ICQ   Вверх
stab
Дата 1.7.2007, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



используй экземпляр класса AutoResetEvent, храни ссылку в статическом члене, имя например ObjectAvailable, создай его в signaled состоянии в статическом конструкторе. при создании твоего объекта, ждать этого события, при "разгрузке" - сигналить.


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
anthony
Дата 1.7.2007, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 25.6.2007
Где: Украина

Репутация: 1
Всего: 5



Код

namespace TestCS {

    using System;
    using System.Threading;

    public class Singleton : IDisposable {

        public Singleton ( ) {
            while ( IsCaptured ) {
                Console.WriteLine ( "Object could not be created, because previous instance is not disposed." );
                Thread.Sleep ( 100 );
            }
            Capture ( this );
        }


        #region IDisposable Members

        public void Dispose ( ) {
            Release ( );
            GC.SuppressFinalize ( this );
        }

        #endregion

        public static bool IsCaptured {
            get {
                return !ReferenceEquals ( CurrentInstance_, null );
            }
        }

        private static void Capture ( Singleton obj ) {
            if ( ReferenceEquals ( obj, null ) ) {
                throw new ArgumentNullException ( );
            }
            if ( IsCaptured ) {
                throw new InvalidOperationException ( );
            }
            CurrentInstance_ = obj;
        }

        private static void Release ( ) {
            if ( !IsCaptured ) {
                throw new ArgumentNullException ( );
            }
            CurrentInstance_ = null;
        }

        private static Singleton CurrentInstance_;
    }

    class Program {
        internal static void Main ( string [ ] args ) {
            Console.WriteLine ( "Creating object a" );
            Singleton a = new Singleton ( );
            Console.WriteLine ( "Object a created" );
            Thread thread = new Thread ( new ThreadStart ( CreateSingleton ) );
            thread.Start ( );
            Thread.Sleep ( 500 );
            a.Dispose ( );
        }

        public static void CreateSingleton ( ) {
            Console.WriteLine ( "Creating object b" );
            Singleton b = new Singleton ( );
            Console.WriteLine ( "Object b created" );
        }
    }
}


Код

namespace TestCS {

    using System;
    using System.Threading;

    public class Singleton : IDisposable {

        public Singleton ( ) {
            while ( IsCaptured ) {
                Thread.Sleep ( 100 );
            }
            Capture ( this );
        }


        #region IDisposable Members

        public void Dispose ( ) {
            Release ( );
            GC.SuppressFinalize ( this );
        }

        #endregion

        public static bool IsCaptured {
            get {
                return !ReferenceEquals ( CurrentInstance_, null );
            }
        }

        private static void Capture ( Singleton obj ) {
            if ( ReferenceEquals ( obj, null ) ) {
                throw new ArgumentNullException ( );
            }
            if ( IsCaptured ) {
                throw new InvalidOperationException ( );
            }
            CurrentInstance_ = obj;
        }

        private static void Release ( ) {
            if ( !IsCaptured ) {
                throw new ArgumentNullException ( );
            }
            CurrentInstance_ = null;
        }

        private static Singleton CurrentInstance_;
    }

    class Program {
        internal static void Main ( string [ ] args ) {
            Console.WriteLine ( "Creating object a" );
            Singleton a = new Singleton ( );
            Console.WriteLine ( "Object a created" );
            Thread thread = new Thread ( new ThreadStart ( CreateSingleton ) );
            thread.Start ( );
            Thread.Sleep ( 500 );
            a.Dispose ( );
        }

        public static void CreateSingleton ( ) {
            Console.WriteLine ( "Creating object b" );
            while ( Singleton.IsCaptured ) {
                Console.WriteLine ( "Object could not be created, because previous instance is not disposed." );
                Thread.Sleep ( 50 );
            }
            Singleton b = new Singleton ( );
            Console.WriteLine ( "Object b created" );
        }
    }
}


Это сообщение отредактировал(а) anthony - 1.7.2007, 13:59
PM MAIL ICQ   Вверх
stab
Дата 1.7.2007, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



anthony, вы не учли одного:

Цитата(Red Wind @  1.7.2007,  16:41 Найти цитируемый пост)
поток ждал пока первый экземпляр класса не будет разружен



--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
anthony
Дата 1.7.2007, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 25.6.2007
Где: Украина

Репутация: 1
Всего: 5



Код

        public static void CreateSingleton ( ) {
            Console.WriteLine ( "Creating object b" );
            Console.WriteLine ( "Waiting..." );
            // Ожидание, пока предыдущий объект не будет уничтожен.
            while ( Singleton.IsCaptured ) {
                Console.WriteLine ( "Object could not be created, because previous instance is not disposed." );
                Thread.Sleep ( 50 );
            }
            Singleton b = new Singleton ( );
            Console.WriteLine ( "Object b created" );
        }



Цитата

Creating object a
Object a created
Creating object b
Waiting...
Object could not be created, because previous instance is not disposed.
Object could not be created, because previous instance is not disposed.
Object could not be created, because previous instance is not disposed.
Object could not be created, because previous instance is not disposed.
Object could not be created, because previous instance is not disposed.
Object could not be created, because previous instance is not disposed.
Object could not be created, because previous instance is not disposed.
Object could not be created, because previous instance is not disposed.
Object could not be created, because previous instance is not disposed.
Object a disposed
Object b created


Это сообщение отредактировал(а) anthony - 1.7.2007, 14:17
PM MAIL ICQ   Вверх
stab
Дата 1.7.2007, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



anthony, в терминах многопоточного программирования "ждал" - это не есть проверка в цикле. если вам не жалко жечь свой процессор на проверке "while (Singleton.IsCaptured)", то пожалуйста. можете запустить свой код и убедиться, что загрузка процессора 100%.


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
anthony
Дата 1.7.2007, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 25.6.2007
Где: Украина

Репутация: 1
Всего: 5



Код

namespace TestCS {

    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Runtime.Remoting.Contexts;

    [Synchronization]
    public class Singleton : IDisposable {

        private Singleton ( string name ) {
            Name = name;
        }

        #region IDisposable Members

        public void Dispose ( ) {
            Release ( );
            GC.SuppressFinalize ( this );
        }

        #endregion

        public override string ToString ( ) {
            return Name;
        }

        public string Name;

        static Singleton ( ) {
            Expectants = new List<Singleton> ( );
        }

        public static void AsyncCreate ( string name ) {
            Singleton created = new Singleton ( name );
            if ( Captured ) {
                Expectants.Add ( created );
            } else {
                Capture ( created );
            }
        }

        private static bool Captured {
            get {
                return !ReferenceEquals ( Current, null );
            }
        }

        public static event EventHandler AsyncCreateComplete;

        private static void Capture ( Singleton obj ) {
            if ( ReferenceEquals ( obj, null ) ) {
                throw new ArgumentNullException ( );
            }
            if ( Captured ) {
                throw new InvalidOperationException ( );
            }
            Current = obj;
            if ( !ReferenceEquals ( AsyncCreateComplete, null ) ) {
                AsyncCreateComplete ( obj, null );
            }
        }

        private static void Release ( ) {
            if ( !Captured ) {
                throw new InvalidOperationException ( );
            }
            Current = null;
            if ( Expectants.Count > 0 ) {
                Singleton next = Expectants [ 0 ];
                Expectants.RemoveAt ( 0 );
                Capture ( next );
            }
        }

        private static Singleton Current;
        private static List<Singleton> Expectants;
    }

    class Program {
        internal static void Main ( string [ ] args ) {
            Console.WriteLine ( "Creating object a" );
            Singleton.AsyncCreateComplete += new EventHandler ( Singleton_AsyncCreateComplete );
            Singleton.AsyncCreate ( "a" );
            Thread thread = new Thread ( new ThreadStart ( CreateSingleton ) );
            thread.Start ( );
            Thread.Sleep ( 500 );
            if ( !ReferenceEquals ( Created, null ) ) {
                Created.Dispose ( );
            }
        }

        static void Singleton_AsyncCreateComplete ( object sender, EventArgs e ) {
            Console.WriteLine ( "Object {0} created.", sender.ToString ( ) );
            Created = ( Singleton ) sender;
        }

        public static void CreateSingleton ( ) {
            Console.WriteLine ( "Creating object b" );
            Singleton.AsyncCreate ( "b" );
        }

        private static Singleton Created;
    }
}

PM MAIL ICQ   Вверх
stab
Дата 1.7.2007, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



наш ответ чемберлену  smile 

Код

using System;
using System.Threading;

namespace Vingrad.SingleThreadedObjectSample
{
    public class SingleThreadedObject
    {
        private static object m_syncRoot = new object();

        public SingleThreadedObject()
        {
            Monitor.Enter(m_syncRoot);
            Console.WriteLine("{0} creates the object.", Thread.CurrentThread.Name);
        }

        public void Release()
        {
            Console.WriteLine("{0} releases the object.", Thread.CurrentThread.Name);
            Monitor.Exit(m_syncRoot);
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "Main thread";
            SingleThreadedObject ownedObject1 = new SingleThreadedObject();
            SingleThreadedObject ownedObject2 = new SingleThreadedObject();

            ConcurrentThread thread1 = new ConcurrentThread("1st thread");
            ConcurrentThread thread2 = new ConcurrentThread("2nd thread");

            Thread.Sleep(2 * 1000);
            ownedObject1.Release();

            Thread.Sleep(2 * 1000);
            ownedObject2.Release();

            thread1.Join();
            thread2.Join();

            Console.WriteLine("THE END");
            Console.ReadLine();
        }

        private class ConcurrentThread
        {
            private Thread m_thread;

            public ConcurrentThread(string name)
            {
                m_thread = new Thread(ThreadProc);
                m_thread.Name = name;
                m_thread.Start();
            }

            private void ThreadProc()
            {
                SingleThreadedObject ownedObject = new SingleThreadedObject();
                Thread.Sleep(2 * 1000);
                ownedObject.Release();
            }

            public void Join()
            {
                m_thread.Join();
            }
        }
    }
}


объекты класса SingleThreadedObject могут жить только в одном потоке. в примере создаётся в общей сложности четыри объекта, два в главном потоке, и по одному на каждый конкурирующий поток. три объекта живут 2 секунды, и один 4, после чего помечаются потоками, как более им не нужные. по-мойму лаконично и удобно.

з.ы. идея с событиями приводила к блокировке потока при попытке создания потоком более чем одного объекта SingleThreadedObject, с монитором ещё проще получилось..


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
Red Wind
Дата 1.7.2007, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 280
Регистрация: 25.6.2004
Где: Минск

Репутация: нет
Всего: 2



Всем спасибо за помощ, вроде разобрался.
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0564 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.