Pwershell WorkFlow

martedì 02 settembre 2014 - 15.06
Tag Elenco Tags  Powershell

slavishdany Profilo | Newbie

Buongiorno,
Vorrei sottoporvi un mio problema.
ho creato uno script in powershell che copia in parallelo dei file che vanno migrati tra due share.
Fino all'utilizzo del workflow con il foreach-parallel tutto ok. Il problema si pone quando devo scrivere il log.
Essendo un parallel ho il problema degli accessi concorrenziali.
Ho provato con un mutex ma a quanto pare non gli piace un granchè.Voi sapete per caso come fare?
Grazie mille :)
Danilo

0v3rCl0ck Profilo | Guru

se il processo è lo stesso, dovresti potere effettuare una sincronizzazione attorno alla scrittura appunto con un mutex o lock/memorybarrier, poi devi stare attento a come apri il file, ci sono diversi livelli di accesso (FileMode, FileAccess, FileShare: http://msdn.microsoft.com/en-us/library/y973b725.aspx).

Se usi un framework di logging, come log4net, già risolve queste problematiche sfruttando mutex, buffer, eccc... dove necessario, e sicuramente all'interno dello stesso processo non avrai alcun problema, mentre per logging cross-process, log4net ha un LockingModel che può essere specificato a InterProcessLock (http://logging.apache.org/log4net/release/sdk/log4net.Appender.FileAppender.html), sfruttando un mutex globale di sistema, ma tutto questo degrata tantissimo le performance, questo poi dipende dal carico della tua applicazione.

Ad ogni modo se rimani all'interno dello stesso processo, log4net è thread-safe e puoi tranquillamente usarlo senza porti il problema, se invece devi fare qualcosa di tuo prova a dare un occhio direttamente al codice sorgente del FileAppender di log4net:

http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net/Appender/FileAppender.cs?view=markup

come vedrai il livello minimo di lock che fa, è per la gestione multi-thread:

override protected void Append(LoggingEvent loggingEvent) { if (m_stream.AcquireLock()) { try { base.Append(loggingEvent); } finally { m_stream.ReleaseLock(); } } } ------------------------------------------------------------------------ public bool AcquireLock() { bool ret=false; lock(this) { if (m_lockLevel==0) { // If lock is already acquired, nop m_realStream=m_lockingModel.AcquireLock(); } if (m_realStream!=null) { m_lockLevel++; ret=true; } } return ret; }

quindi come minimo acquisisce un lock in memoria per fare da scudo agli eventuali thread concorrenti che potrebbero andare a scrivere su log, inoltre acquisice anche tipi diversi di lock su file per eventuali processi concorrenti, che con un semplice lock non potrebbero essere sincronizzati, e quindi si devono sfruttare altre tecniche di sincronizzazione, o aprendo e chiudendo lo stream ad ogni scrittura, o sfruttando un mutex globale. Se devi fare scritture multi processo, consiglio di vedere altre tecniche, come il remote logging, dove le loggate vengono spedite con un protocollo di remoting, e dove c'è in ascolto un server (sink) che serializza e scrive tutto su un singolo file (vedi anche nelle FAQ di log4net, alla sezione "How do I get multiple process to log to the same file?" http://logging.apache.org/log4net/release/faq.html).

Ciao!

Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5