В "Шаг 84 - Критическая секция" Артём рассказал про критические секции, хочу некоторые моменты про критические секции и добавить кое-что про мьютексы. Там создавалась критическая секция в которой блокировалась переменная sync.
class MainClass { public static Object sync = "var lock"; ... public static void Proc1() { lock(sync) { ... } } }
Но она имела тип object. Всё конечно хорошо, но что бы мы делали если бы она имела тип int или просто нужно было бы, что - то синхронизировать в статическом методе. Для этого нужно было бы залочить следующим образом lock(typeof(MainClass)) По идее lock имеет следующий вид lock(expression), где expression экземпляр объекта, причём он должен быть, как я понял ссылочного типа(класс, интерфейс, делегат и т.д.) Значения типа int и т.д. тут не катят. Но если мы хотим защитить статическую переменную или критическая секция находится в static методе, то expression будет иметь вид typeof(class).
Теперь перейдём к мьютексам. Аналогом мьтексов в .Net является класс Mutex. Три конструктора позволяют создать объект мьютекс
Mutex(); Mutex(bool initiallyOwned); Mutex(bool initiallyOwned, string name);
Пример
Mutex mutex = new Mutex(false, "testmutex");
Первый конструктор я думаю объяснять не надо, второй конструктор создаёт мьютекс, если initiallyOwned равна trueWaitOne и ReleaseMutex, первый метод:
public virtual bool WaitOne(); public virtual bool WaitOne(TimeSpan, bool); public virtual bool WaitOne(int , bool);
Первый ждёт неопределенно долгое время, второй и третий метод будут ждать в течении некоторого промежутка времени выраженного TimeSpan или int. Также есть методы WaitAny и WaitAll
public static bool WaitAll(WaitHandle[]); public static bool WaitAll(WaitHandle[], int, bool); public static bool WaitAll(WaitHandle[], TimeSpan, bool); public static int WaitAny(WaitHandle[]); public static int WaitAny (WaitHandle[], int, bool); public static int WaitAny (WaitHandle[], TimeSpan, bool);
Метод WaitAny ждёт освобождения любого объекта из массива WaitHandle, а WaitAll всех. Класс WaitHandle является предком мьютексов, потоков, событий, процессов, AppDomain и т.д., так что в этот массив можно запихивать разные объекты, одновременно там может быть и событие и мьютекс. Функция ReleaseMutex() уменьшает счётчик мьютекса на единицу. Пример создания мьютекса и его использование.
Mutex mutex = new Mutex(false, "testmutext); mutex.WaitOnce(); someproc(); ..... mutex.ReleaseMutex();
Есть ещё два интересных метода SetHandle и int GetHandle()
SetHandle(int handle) int GetHandle()
Первый устанавливает native handle("родной указатель для операционки" не могу подобрать аналог в русском), тот который мы получаем при вызове API функции CreateMutex второй служит, чтобы получить хандл, который используется мьютексом. Далее приводится небольшой пример, создаются два листбокса и 4 потока, в первых двух для синхронизации используются критические секции, во вторых двух мьютексы. И каждый поток добавляет в листбокс строку. Интересный результат получается при запуске нескольких приложений, критические секции как работали так и будет работать, а вот с мьютексами другое дело. Чем больше приложений тем более, медленней будут добавлятся строки там где используются мьютексы, так как у нас создаются "именованные" мьютексы(как известно мьютексы используются для синхронизации приложений). Странная вещь почему - то они обрабатыватся странным способом, сперва два мьютекса в одном приложении, потом два в другом и т.д., я всё таки надеялся, они будут добавляться не по два одновременно за раз(вроде как мьютексы стоят в очереди FIFO). Странная вещь ещё наблюдалась если в API функциях при создании потоков можно было, передавать при старте Thread какое-то значение, то здесь нет. В делегате ThreadStart нет передаваемых значений. Приходилось создавать для каждого потока класс, обидно конечно. В примере закоментированы строки для сихронизации по static переменной
// static int LockVariable = 0; ... lock(form.CriticalSection)//typeof(MyThreadFunction)
В первой строке уберите //, а во второй вместо Form.CriticalSection вставьте typeof(MyThreadFunction).