Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.06.2018, 12:25   #1
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию Межпроцессная синхронизация

Здравствуйте.
Есть вот такой фрагмент кода (C#):
Код:
Mutex bufferSync;
do
{ // запуск синхронизации буфера
	try
	{
		bufferSync=new Mutex(true,"BufferSync_Mutex");
	} catch
	{ // по идее, мютекс не должен сотвориться, если он уже где то создан
		bufferSync=null;
		Thread.Sleep(100);
	}
} while (bufferSync==null);

/*
	работа с буфером обмена (Clipboard)
*/

// остановка синхронизации буфера
bufferSync.ReleaseMutex();
bufferSync.Close();
bufferSync.Dispose();
bufferSync=null; // об этом можете не спрашивать, пускай просто будет здесь
Этот код вызывается каждые ~20 секунд по пять раз, в одном процессе. Предполагается работа одновременно до 4 процессов, но это ограничивается оперативной памятью и мощью процессора компьютера.

Если так сказать, "в теории", то всё ли нормально по коду ? Или можно что то изменить в лучшую сторону, и желательно в техническом плане, а не в эстетической "читабельности" кода ... =)
Ну там может тайминги подкрутить, или что по серьёзней.

Пока я не дошёл до момента, когда нужно будет протестировать, но и вообще, лучше сразу сделать так, что бы работало как положено, ибо тестирование предполагается в процессе непосредственно рабочем, когда уже должно быть всё налажено. Во всяком случае, при работе одной программы всё работает нормально; нужно что бы при работе нескольких программ процессы не дрались за буфер обмена.
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Старый 19.06.2018, 13:29   #2
eoln
Старожил
 
Аватар для eoln
 
Регистрация: 26.04.2008
Сообщений: 2,645
По умолчанию

Буфер обмена можно отслеживать с помощью WM_DRAWCLIPBOARD и WM_CHANGECBCHAIN, и не нужно будет вручную циклически его мониторить.

Методы ожидание мьютекса уже присутствует в классе, WaitOne и подобное в зависимости от задачи https://msdn.microsoft.com/ru-ru/lib...v=vs.110).aspx
eoln вне форума Ответить с цитированием
Старый 19.06.2018, 13:51   #3
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,357
По умолчанию

Зачем создавать мьютекс каждый раз?
Зачем он вообще нужен - работа с клипбордом (да и любое WIN32 API) потокобезопасно.
Собственно, из приведенного фрагмента понятно только про сам мьютекс, который по сути излишен.
Сама концепция таймера порочна по своей сути, кроме случаев, когда нужен timeout или нет сигнала.
waleri вне форума Ответить с цитированием
Старый 19.06.2018, 14:24   #4
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

Цитата:
Если так сказать, "в теории", то всё ли нормально по коду ?
Не всё. По факту обращения к мютексу встают в очередь, и висят в бесконечном цикле, пока последний пользователь мютекса не освободит его имя для след. пользователя.
Цитата:
нужно что бы при работе нескольких программ процессы не дрались за буфер обмена.
Поставьте их в очередь, да и вообще можно попробовать использовать IPC, где один из процессов выступает хостом (держит и контролирует буфер), остальные дочерними, ждрут когда хост передаст управление буфером след. в очереди дочернему процессу
Человек_Борща вне форума Ответить с цитированием
Старый 19.06.2018, 20:33   #5
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от eoln Посмотреть сообщение
Методы ожидание мьютекса уже присутствует в классе, WaitOne и подобное
У меня нет ссылок на объект мютекса, который был создан когда либо в каком либо другом процессе. Мне должно помочь это ?

Цитата:
Сообщение от waleri Посмотреть сообщение
работа с клипбордом (да и любое WIN32 API) потокобезопасно
Да это так, но конфликты происходят на уровне данных. Одна программа пытается пропихнуть свой набор данных, другая - тоже свой. И без синхронизации будет происходить произвольная замена данных в буфере: процесс 1 разместил свои данные, но по каким либо причинам не успел их выложить до того, как процесс 2 разместил свои данные. В итоге для обоих процессов с изначально разными данными в буфере обмена данные для второго процесса ...

Цитата:
Сообщение от waleri Посмотреть сообщение
понятно только про сам мьютекс
А остальное не играет никакой роли в моём вопросе, суть в том, что программе нужно завести данные в буфер обмена, и потом отправить в элемент ChromeDriver'а комбинацию клавиш Ctrl+V. Вместо посимвольного ввода всего текста через SendKeys.
Уже много воды.
Из этого понятно, что если будут происходить выше описанные конфликты между процессами - будут выше описанные проблемы.

Цитата:
Сообщение от waleri Посмотреть сообщение
Сама концепция таймера порочна по своей сути
Не таймер, я просто воткнул задержку, что бы процесс не грузил систему.

Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
висят в бесконечном цикле, пока последний пользователь мютекса не освободит его имя
Вот этого я не понял ...
Линк, разве не будет выпадать страшный WaitHandleCannotBeOpenedException ?
Яж поэтому и взял в try-catch ...

Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
можно попробовать использовать IPC, где один из процессов выступает хостом
Чёт сложна, это либо "первый хост, остальные дочерние", либо как это было бы правильно - хост это отдельный процесс, то есть - отдельная программа, а рабочие процессы собственно дочерние. Головняк какой то ...
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Старый 19.06.2018, 20:45   #6
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,357
По умолчанию

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
процесс 1 разместил свои данные, но по каким либо причинам не успел их выложить до того, как процесс 2 разместил свои данные. В итоге для обоих процессов с изначально разными данными в буфере обмена данные для второго процесса ...
Вы все равно не будете знать когда данные будут получены... ненадежная схема.
Не знаю зачем надо изгаляться таким образом, ну да ладно, дело хозяйское.
Просто создайте мьютекс один раз при запуске процесса и только делайте lock/unlock. Имена мюьтексов глобальны (с оговорками, но вам не до них).
waleri вне форума Ответить с цитированием
Старый 19.06.2018, 21:17   #7
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Имена мюьтексов глобальны (с оговорками, но вам не до них)
То что мютекс глобальный в пределах домена я знаю ... =)

Цитата:
Сообщение от waleri Посмотреть сообщение
создайте мьютекс один раз при запуске процесса
Ну да, это в одном процессе, а у меня предполагается несколько.
И если я правильно понял эти слова
Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
обращения к мютексу встают в очередь, и висят в бесконечном цикле
То при попытке создать существующий мютекс функция конструктора зависнет в бесконечном цикле.
Тогда сначала OpenExisting, и если я получил WaitHandleCannotBeOpenedException - то только тогда создавать мютекс. Если же я не правильно понял эти слова - то тогда не важно, откуда я получу исключение.
Вот так тогда да, WaitOne-ReleaseMutex и полетели.

Цитата:
Сообщение от waleri Посмотреть сообщение
Вы все равно не будете знать когда данные будут получены
В смысле ? Получены кем ? Буфером ?
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Старый 20.06.2018, 00:15   #8
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,357
По умолчанию

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
при попытке создать существующий мютекс функция конструктора зависнет в бесконечном цикле
Только если мьютекс в момент создания заперт а вы пытаетесь создать запертый мьютекс, да и то это будет не бесконечный цикл а ожидание.
Весь смысл именованных ресурсов в том, чтоб они были доступны из разных процессов.
waleri вне форума Ответить с цитированием
Старый 20.06.2018, 01:30   #9
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Чёт сложна, это либо "первый хост, остальные дочерние", либо как это было бы правильно - хост это отдельный процесс, то есть - отдельная программа, а рабочие процессы собственно дочерние. Головняк какой то ...
Вот после
Цитата:
Во всяком случае, при работе одной программы всё работает нормально; нужно что бы при работе нескольких программ процессы не дрались за буфер обмена.
стало сложно уже мне, понять что же Вам собственно надо


Цитата:
Вот этого я не понял ...
Линк, разве не будет выпадать страшный WaitHandleCannotBeOpenedException ?
Яж поэтому и взял в try-catch ...
У Вас ведь задача шарить буфер между процессами таким образом, чтобы друг-другу процессы не мешали. У вас они друг-другу мешают, т.к. один занимает буфер (блокирует), прочие курят эксепшен.
Человек_Борща вне форума Ответить с цитированием
Старый 20.06.2018, 05:21   #10
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
да и то это будет не бесконечный цикл а ожидание
Про бесконечный цикл не мои слова. Я думал тут все поняли о чём речь ...
Но не это важно, важно то, что в конструкторе выполняется ожидание, вместо положенного по сути WaitHandleCannotBeOpenedException, иль чего нибудь ещё. Независимо от того, заперт существующий мютекс, или нет. Он уже есть - знать попытка создать такой же должна закончиться эксепшеном.
Где то здесь же мне и рассказывали, где-где, а вот в конструкторе точно не должно быть никаких "ожидающих" циклов. Ну то и ладно, не я создавал, и не мне судить.

Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
один занимает буфер (блокирует), прочие курят эксепшен
Пока один "заблокировал буфер", остальные курят эксепшн до тех пор, пока первый не освободит буфер. И да, без синхронизации эксепшенов не будет. Как мы уже выяснили - эксепшенов вообще не будет, ибо в системе образуется мютекс с таким же именем, и тут же запирается. Хотя опять же, эксепшн может и успеет вылететь, если мютекс был создан, но по каким либо причинам ещё не успел закрыться.
Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Этот код вызывается каждые ~20 секунд по пять раз, в одном процессе
Собственно идея была такова: пока эксепшн - ждать, потом кто первый встал - того и тапки.

Здесь я пришёл узнать, как улучшить эту конструкцию, и мы пришли к выводу, что лучше сразу создать мютекс, открывать существующий из других процессов, и играться блокировками:
Код:
bufferSync.WaitOne();
/*
	работа с буфером
	по большому счёту не важно, что здесь будет находиться, будь то аппаратный I/O на USB/HDD
	или что там в системе не терпит параллельного ввода-вывода
*/
bufferSync.ReleaseMutex();
Вопрос только вот в чём: если все три процесса зависли в WaitOne, то кто первый вылетит оттуда, когда четвёртый процесс разблокирует мютекс ...
Уж не тот ли, у кого первого закончится тайминг перед проверкой ? Или там что то по серьёзней типа очереди ?
Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
обращения к мютексу встают в очередь, и висят в бесконечном цикле

Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
стало сложно уже мне, понять что же Вам собственно надо
Для этого я здесь, объясняю =)
Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
процесс 1 разместил свои данные, но по каким либо причинам не успел их выложить до того, как процесс 2 разместил свои данные. В итоге для обоих процессов с изначально разными данными в буфере обмена данные для второго процесса
Подпись ? Не, не слышал ...

Последний раз редактировалось OmegaBerkut; 20.06.2018 в 06:41.
OmegaBerkut вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Синхронизация kuba1981 PHP 9 06.05.2013 11:39
Синхронизация БД Bright-rider БД в Delphi 3 19.06.2012 07:32
Межпроцессная комуникация(Windows)mailslots Flattery Win Api 0 10.12.2011 13:41
Синхронизация kostyan142 Общие вопросы по Java, Java SE, Kotlin 6 13.01.2010 01:39
Синхронизация yarilo Софт 2 07.08.2009 15:50