Scambiare informazioni tra due diverse applicazioni

venerdì 16 gennaio 2015 - 08.46
Tag Elenco Tags  C#  |  .NET 4.0  |  Windows 7  |  Visual Studio 2010

hydra Profilo | Junior Member

Salve a tutti, spero che possiate aiutarmi con questo piccolo problema, ho fatto qualche ricerca in internet ma non ho trovato informazioni utili.
In pratica devo monitorare dei tempi di esecuzione in un'applicazione principale tramite un'applicazione secondaria e ho quindi necessità, dall'applicazione secondaria, di poter accedere a un limitato numero di variabili dell'applicazione principale. Sapete dirmi se è possibile farlo e, se si, in che modo? Oppure mi potete suggerire qualche strada alternativa?
Grazie in anticipo.

luigidibiasi Profilo | Guru

Puoi usare IPC oppure shared memory o una dll condivisa.

Online trovi tanti tutorial per velocizzarti lo sviluppo
Luigi Di Biasi

http://www.dibiasi.it/
http://www.luigidibiasi.it
http://yadamp.unisa.it/
http://yadamp.unisa.it/grimd
http://www.cilentiamoci.it

0v3rCl0ck Profilo | Guru

Ciao, dell'applicazione principale ne hai il controllo? puoi modificarla? se si, ti consiglio di aggiungere dei performance counter che poi potranno essere letti da qualsiasi altro software nonchè quelli integrati di windows. Oppure puoi vedere dei framework più moderni come metrics.net: http://github.com/danielcrenna/metrics-net

ti lascio anche un paio di librerie per gestire i performance counter senza scrivere tonnellate di codice a mano:

http://perfmoncounterhelper.codeplex.com/
http://github.com/qoollo/performance-counters
http://github.com/DmitryNaumov/PerformanceCounters



Michael Denny | Microsoft Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.net
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

hydra Profilo | Junior Member

Grazie a entrambi per le risposte. Forse non sono stato molto chiaro nell'illustrare la situazione, io non devo monitorare il tempo di esecuzione dell'intera applicazione, devo monitorare il tempo di esecuzione di alcune parti di codice. Per farvi capire lo scenario, l'applicazione principale si occupa di gestire una periferica posta su una linea di produzione, generalmente monitora la situazione ma invia anche comandi alla stazione. Il fatto è che dopo alcune ore di lavoro continuo il tutto inizia a rallentare, per cui volevo andare ad acquisire il tempo di esecuzione di alcune parti di codice e visualizzare i tempi in un grafico, ma per non appesantire ulteriormente l'applicazione principale e falsare i dati avevo pensato appunto di farlo tramite una seconda applicazione. Vi dico inoltre che ho il controllo del codice dell'applicazione principale, quindi posso fare le modifiche che voglio, ma non ho a disposizione il pc quindi devo fare dei test e implementare una soluzione in ufficio e quindi inviarla al cliente.

Guardando un po' in rete ho visto che ci sono vari metodi per poter accedere alle variabili tra le varie applicazioni, uno di questi (che è quello che sto cercando di implementare adesso) è il Memory Mapped File. Sto appunto eseguendo dei test ma ho un problema, ossia il dato scritto dall'applicazione A non viene correttamente letto dall'applicazione B. Da quello che ho capito il valore letto dall'applicazione B viene scritto dall'applicazione A, perchè se fermo la scrittura dall'applicazione A la lettura dall'applicazione B viene interrotta, solo che i dati non sono uguali. Per farvi un esempio, se A scrive 4.5255 B legge 1.784443177642601E-307

Applicazione A - scrittura:

private MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("COMMTEST", 1); private double tmr = 0; private bool val = false; private System.Diagnostics.Stopwatch Counter = new System.Diagnostics.Stopwatch(); public Form1() { InitializeComponent(); } private void timer1_Tick(object sender, EventArgs e) { Counter.Restart(); val = !val; checkBox1.Checked = val; checkBox2.Checked = val; checkBox3.Checked = val; checkBox4.Checked = val; checkBox5.Checked = val; tmr = Counter.Elapsed.TotalMilliseconds; label1.Text = string.Format("{0:0.0000}", tmr); // Per inviare i dati sil MMF bool mutexCreated; Mutex mutex = new Mutex(true, "testmutex", out mutexCreated); using (MemoryMappedViewStream stream = mmf.CreateViewStream()) { BinaryWriter writer = new BinaryWriter(stream); writer.Write(tmr); } mutex.WaitOne(); //mutex.ReleaseMutex(); } private void Form1_Load(object sender, EventArgs e) { timer1.Start(); }

Applicazione B - lettura:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Attualmente sto facendo un test con una variabile, poi dovrei andare a monitorare diverse variabili (non molte ma più di una). Ho usato dei timer perchè l'applicazione di cui sto parlando utilizza un ciclo continuo, quindi dovrebbe inviare continuamente i dati e l'applicazione monitor leggerli continuamente.
Spero che si riesca a trovare una qualche soluzione. Di nuovo grazie.

0v3rCl0ck Profilo | Guru

Non ho mai usato la classe MemoryMappedFile, principalmente serve per lavorare su file estremamente grandi, io non seguirei questa strada, utilizzerei i performance counter, che esistono proprio per quello che devi fare, e monitorizzare ogni singola parte di codice che vuoi, anche solo 1 riga di codice, sei tu che decidi cosa monitorizzare. Sfruttando i performance counter tra l'altro non dovrai neanche scrivere il software B, perchè ne esistono già centinaia già fatti, tra cui quello di windows "Performance Monitor" che ti presenterà i dati su grafico:


999x710 32Kb




Michael Denny | Microsoft Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.net
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

un console app di esempio che usa i performance counter, direttamente utilizzando la classe di .net:

using System; using System.Collections; using System.Collections.Specialized; using System.Diagnostics; public class App { private static PerformanceCounter avgCounter64Sample; private static PerformanceCounter avgCounter64SampleBase; public static void Main() { ArrayList samplesList = new ArrayList(); // If the category does not exist, create the category and exit. // Performance counters should not be created and immediately used. // There is a latency time to enable the counters, they should be created // prior to executing the application that uses the counters. // Execute this sample a second time to use the category. if (SetupCategory()) return; CreateCounters(); CollectSamples(samplesList); CalculateResults(samplesList); } private static bool SetupCategory() { if ( !PerformanceCounterCategory.Exists("AverageCounter64SampleCategory") ) { CounterCreationDataCollection counterDataCollection = new CounterCreationDataCollection(); // Add the counter. CounterCreationData averageCount64 = new CounterCreationData(); averageCount64.CounterType = PerformanceCounterType.AverageCount64; averageCount64.CounterName = "AverageCounter64Sample"; counterDataCollection.Add(averageCount64); // Add the base counter. CounterCreationData averageCount64Base = new CounterCreationData(); averageCount64Base.CounterType = PerformanceCounterType.AverageBase; averageCount64Base.CounterName = "AverageCounter64SampleBase"; counterDataCollection.Add(averageCount64Base); // Create the category. PerformanceCounterCategory.Create("AverageCounter64SampleCategory", "Demonstrates usage of the AverageCounter64 performance counter type.", PerformanceCounterCategoryType.SingleInstance, counterDataCollection); return(true); } else { Console.WriteLine("Category exists - AverageCounter64SampleCategory"); return(false); } } private static void CreateCounters() { // Create the counters. avgCounter64Sample = new PerformanceCounter("AverageCounter64SampleCategory", "AverageCounter64Sample", false); avgCounter64SampleBase = new PerformanceCounter("AverageCounter64SampleCategory", "AverageCounter64SampleBase", false); avgCounter64Sample.RawValue=0; avgCounter64SampleBase.RawValue=0; } private static void CollectSamples(ArrayList samplesList) { Random r = new Random( DateTime.Now.Millisecond ); // Loop for the samples. for (int j = 0; j < 100; j++) { int value = r.Next(1, 10); Console.Write(j + " = " + value); avgCounter64Sample.IncrementBy(value); avgCounter64SampleBase.Increment(); if ((j % 10) == 9) { OutputSample(avgCounter64Sample.NextSample()); samplesList.Add( avgCounter64Sample.NextSample() ); } else Console.WriteLine(); System.Threading.Thread.Sleep(50); } } private static void CalculateResults(ArrayList samplesList) { for(int i = 0; i < (samplesList.Count - 1); i++) { // Output the sample. OutputSample( (CounterSample)samplesList[i] ); OutputSample( (CounterSample)samplesList[i+1] ); // Use .NET to calculate the counter value. Console.WriteLine(".NET computed counter value = " + CounterSampleCalculator.ComputeCounterValue((CounterSample)samplesList[i], (CounterSample)samplesList[i+1]) ); // Calculate the counter value manually. Console.WriteLine("My computed counter value = " + MyComputeCounterValue((CounterSample)samplesList[i], (CounterSample)samplesList[i+1]) ); } } //++++++++//++++++++//++++++++//++++++++//++++++++//++++++++//++++++++//++++++++ // Description - This counter type shows how many items are processed, on average, // during an operation. Counters of this type display a ratio of the items // processed (such as bytes sent) to the number of operations completed. The // ratio is calculated by comparing the number of items processed during the // last interval to the number of operations completed during the last interval. // Generic type - Average // Formula - (N1 - N0) / (D1 - D0), where the numerator (N) represents the number // of items processed during the last sample interval and the denominator (D) // represents the number of operations completed during the last two sample // intervals. // Average (Nx - N0) / (Dx - D0) // Example PhysicalDisk\ Avg. Disk Bytes/Transfer //++++++++//++++++++//++++++++//++++++++//++++++++//++++++++//++++++++//++++++++ private static Single MyComputeCounterValue(CounterSample s0, CounterSample s1) { Single numerator = (Single)s1.RawValue - (Single)s0.RawValue; Single denomenator = (Single)s1.BaseValue - (Single)s0.BaseValue; Single counterValue = numerator / denomenator; return(counterValue); } // Output information about the counter sample. private static void OutputSample(CounterSample s) { Console.WriteLine("\r\n+++++++++++"); Console.WriteLine("Sample values - \r\n"); Console.WriteLine(" BaseValue = " + s.BaseValue); Console.WriteLine(" CounterFrequency = " + s.CounterFrequency); Console.WriteLine(" CounterTimeStamp = " + s.CounterTimeStamp); Console.WriteLine(" CounterType = " + s.CounterType); Console.WriteLine(" RawValue = " + s.RawValue); Console.WriteLine(" SystemFrequency = " + s.SystemFrequency); Console.WriteLine(" TimeStamp = " + s.TimeStamp); Console.WriteLine(" TimeStamp100nSec = " + s.TimeStamp100nSec); Console.WriteLine("++++++++++++++++++++++"); } }

preso direttamente dall'msdn: http://msdn.microsoft.com/library/system.diagnostics.performancecounter.aspx



Michael Denny | Microsoft Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.net
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

e un esempio completo di codice sorgente:

http://www.codeproject.com/Articles/8590/An-Introduction-To-Performance-Counters



Michael Denny | Microsoft Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.net
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

hydra Profilo | Junior Member

Grazie, ho controllato l'articolo e mi sembra interessante. Però senti questa: ho scaricato l'esempio e ho provato a scrivere un programma di test prendendo spunto da quell'esempio; l'esempio scaricato funziona, quello che ho scritto io no. Nel senso che il valore che leggo nel performance counter di windows è sempre zero, mentre quello dell'esempio scaricato cambia. Eppure io vado ad inserire un valore.

Questo il codice:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Come puoi notare gran parte del codice l'ho preso papale papale dall'esempio. Non riesco a capire dove sbaglio.

0v3rCl0ck Profilo | Guru

non vedo se hai settato l'handler sul tick del timer, se è tutto quello il codice, manca quello


Michael Denny | Microsoft Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.net
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-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5