/* * Metodo per cominciare la raccolta di informazioni dal server * In caso di eccezione, vengono fatti due tentativi */ public void startWork() { uint attempt = 2; while (attempt != 0) { try { // Creazione di un thread secondario che riceve dati dal server e aggiorna la lista listener = new MySocketListener(this); ReceiveThread = new Thread(listener.ThreadFcn); Console.WriteLine("Main thread: Call Start, to start ThreadFcn."); ReceiveThread.IsBackground = true; ReceiveThread.Start(); percentageTimer.Start(); Console.WriteLine("Main thread: Call Join(), to wait until ThreadFcn ends."); attempt = 0; } catch (OutOfMemoryException) { ExceptionHandler.MemoryError(attempt, this.ContainerTab.MainWindow); } } }
/// <summary> /// Funzione che inizia la raccolta delle informazioni dal server /// </summary> public void StartServerDataExchange() { uint attempt = 2; while (attempt != 0) { try { Listener = new SocketListener(this); // Thread secondario che si pone in attesa di informazioni dal server ListenerThread = new Thread(Listener.SocketThreadListen); Console.WriteLine("Main thread: Call Start, to start ThreadFcn."); // Mettiamo il thread in background ListenerThread.IsBackground = true; ListenerThread.Start(); // Avvio del timer di refresh della percentuale PercentageRefreshTimer.Start(); Console.WriteLine("Main thread: Call Join(), to wait until ThreadFcn ends."); attempt = 0; } catch (OutOfMemoryException) { ExceptionHandler.MemoryError(attempt, this.ServerTab.MainWndw); } } }
/* * Metodo eseguito da un thread in background per la ricezione dati dal socket * La signature della funzione deve rispettare il delegato ThreadStart */ public void ThreadFcn() { int nread = 0; try { Byte[] myReadBuffer = new Byte[1024]; // Ricezione modifiche dal server while (!stop) { Console.WriteLine("In attesa di ricevere dati dal server..."); // Ricezione tipo modifica: u_short nread = Stream.Read(myReadBuffer, 0, sizeof(ushort)); if (!isReadCorrect(nread, sizeof(ushort))) { return; } // Conversione Network To Host Order ushort mod_convertito = BitConverter.ToUInt16(myReadBuffer, 0); int mod = IPAddress.NetworkToHostOrder((short)mod_convertito); Console.WriteLine("Tipo modifica: {0}", mod); // Ricezione PID del processo: DWORD // La dimensione della DWORD è pari a quella di un uint in C# nread = Stream.Read(myReadBuffer, 0, sizeof(uint)); if (!isReadCorrect(nread, sizeof(uint))) { return; } uint pid = BitConverter.ToUInt32(myReadBuffer, 0); Console.WriteLine("PID: {0}", pid); // Switch sul tipo della modifica switch (mod) { // Caso 0: aggiunta di una nuova applicazione case 0: // Ricezione lunghezza del nome dell'applicazione nread = Stream.Read(myReadBuffer, 0, sizeof(int)); if (!isReadCorrect(nread, sizeof(uint))) { return; } // Conversione Network To Host Order int len_conv = BitConverter.ToInt32(myReadBuffer, 0); Console.WriteLine("lunghezza convertita: {0}", len_conv); int name_len = IPAddress.NetworkToHostOrder(len_conv); Console.WriteLine("lunghezza nome: {0}", name_len); Byte[] buffer_name = new Byte[name_len]; String app_name = String.Empty; // Ricezione del nome dell'applicazione nread = Stream.Read(buffer_name, 0, name_len); if (!isReadCorrect(nread, name_len)) { return; } // Conversione in String try { app_name = System.Text.UnicodeEncoding.Unicode.GetString(buffer_name); app_name = app_name.Replace("\0", String.Empty); } catch (ArgumentException) { app_name = "Senza nome"; } Console.WriteLine("Nome dell'app: {0}", app_name); // Ricezione lunghezza dell'icona nread = Stream.Read(myReadBuffer, 0, sizeof(int)); if (!isReadCorrect(nread, sizeof(uint))) { return; } // Creazione dell'oggetto ApplicationItem con icona di default ApplicationItem app = new ApplicationItem(item.ContainerTab.MainWindow.defaultIcon); app.PID = pid; app.Name = app_name; // Conversione Network To Host Order int icon_conv = BitConverter.ToInt32(myReadBuffer, 0); int icon_len = IPAddress.NetworkToHostOrder(icon_conv); Console.WriteLine("lunghezza icona convertita: {0}", icon_len); // Se la dimensione dell'icona è valida, si sostituisce a quella di default if (icon_len != 0 && icon_len < 1048576) { Console.WriteLine("Icona presente"); // Ricezione icona (in blocchi da 1024 byte) Byte[] buffer_ICON = new Byte[icon_len]; int tot = 0, toread = 1024; while (tot != icon_len) { if (toread > icon_len - tot) { toread = icon_len - tot; } nread = Stream.Read(buffer_ICON, tot, toread); if (nread == 0) { Console.WriteLine("Connessione chiusa durante lettura"); return; } tot += nread; } if (tot != icon_len) { Console.WriteLine("Read fallita: {0}", nread); item.ContainerTab.MainWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { item.ContainerTab.MainWindow.CloseTab(item.ContainerTab); })); } // Codice unsafe perché si fa uso di puntatori // Lettura dell'icona tramite la funzione importata e conversione in bitmap WPF unsafe { fixed(byte *buffer = &buffer_ICON[0]) { IntPtr Hicon = CreateIconFromResourceEx((IntPtr)buffer, (uint)icon_len, 1, 0x00030000, 48, 48, 0); if (Hicon != null) { BitmapFrame bitmap = BitmapFrame.Create(Imaging.CreateBitmapSourceFromHIcon(Hicon, new Int32Rect(0, 0, 48, 48), BitmapSizeOptions.FromEmptyOptions())); if (bitmap.CanFreeze) { bitmap.Freeze(); app.Icon = bitmap; } DestroyIcon(Hicon); } } } } // Aggiunta nuova applicazione e notifica del cambiamento nella lista item.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { lock (item.applications) { item.applications.Add(app); } })); item.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { item.listView_CollectionChanged(item.listView, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, app)); })); break; // Caso 1: rimozione di un'applicazione case 1: Console.WriteLine("Modifica: Rimozione"); // Rimozione dell'applicazione dalla lista Monitor.Enter(item.applications); foreach (ApplicationItem appItem in item.applications) { if (appItem.PID == pid) { Console.WriteLine("Rimozione applicazione: {0}", appItem.Name); Monitor.Exit(item.applications); this.item.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { lock (item.applications) { this.item.applications.Remove(appItem); } })); Monitor.Enter(item.applications); break; } } Monitor.Exit(item.applications); break; // Caso 3: cambio di focus case 2: Console.WriteLine("Modifica: Change Focus"); // Pulizia della selezione precedente this.item.ContainerTab.MainWindow.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { this.item.listView.SelectedItem = null; })); // Applicazione che perde il focus this.item.ContainerTab.MainWindow.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { // Aggiornamento lista app in foreground int index = this.item.ContainerTab.MainWindow.foregroundApps.IndexOf(new ForegroundApp(item.ContainerTab.foregroundApp, 0)); if (index != -1) { if (--this.item.ContainerTab.MainWindow.foregroundApps[index].Count <= 0) { this.item.ContainerTab.MainWindow.foregroundApps.RemoveAt(index); } } })); // Ricerca delle applicazioni coinvolte nel cambiamento Monitor.Enter(item.applications); foreach (ApplicationItem appItem in item.applications) { // Applicazione che guadagna il focus if (appItem.PID == pid) { Console.WriteLine("Pid: {0} - applicazione: {1}", pid, appItem.Name); Monitor.Exit(item.applications); this.item.ContainerTab.MainWindow.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { lock (item.applications) { // Evidenziazione elemento nella tab appItem.IsFocused = true; this.item.listView.SelectedItem = appItem; this.item.ContainerTab.foregroundApp = appItem.Name; // Aggiornamento lista delle app in foreground int index = this.item.ContainerTab.MainWindow.foregroundApps.IndexOf(new ForegroundApp(appItem.Name, 0)); if (index != -1) { this.item.ContainerTab.MainWindow.foregroundApps[index].Count++; } else { ForegroundApp newapp = new ForegroundApp(appItem.Name, 1); this.item.ContainerTab.MainWindow.foregroundApps.Add(newapp); if (!this.item.ContainerTab.MainWindow.foregroundBox.IsEnabled) { this.item.ContainerTab.MainWindow.foregroundBox.SelectedItem = newapp; } } } })); Monitor.Enter(item.applications); } else if (appItem.IsFocused) { appItem.IsFocused = false; } } Monitor.Exit(item.applications); // Aggiornamento delle percentuali item.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { item.percentageUpdate(); })); break; case 3: break; default: Console.WriteLine("Modifica sconosciuta"); break; } } Console.WriteLine("Thread - terminata ricezione dati dal server"); } catch (NullReferenceException) { ExceptionHandler.ReceiveConnectionError(item); } catch (IOException) { ExceptionHandler.ReceiveConnectionError(item); } catch (ObjectDisposedException) { ExceptionHandler.ReceiveConnectionError(item); } catch (ArgumentOutOfRangeException) { ExceptionHandler.ReceiveConnectionError(item); } catch (OutOfMemoryException) { ExceptionHandler.MemoryError(item.ContainerTab.MainWindow); } }
/// <summary> /// Funzione eseguita da un thread in background: riceve dati dal socket /// </summary> public void SocketThreadListen() { int n = 0; try { Byte[] readBuffer = new Byte[1024]; while (!stop) { Console.WriteLine("In attesa di ricevere dati dal server..."); // Ricezione del tipo di modifica effettuata n = Stream.Read(readBuffer, 0, sizeof(ushort)); if (!readSuccessful(n, sizeof(ushort))) { return; } // Conversione del buffer nell'ordine dei byte dell'host (Precedentemente era in ordine di rete) ushort conv_mod = BitConverter.ToUInt16(readBuffer, 0); int ModificationType = IPAddress.NetworkToHostOrder((short)conv_mod); Console.WriteLine("Tipo della modifica: {0}", ModificationType); // Ricezione del PID del processo. E' una DWORD che ha dimensioni pari ad uint n = Stream.Read(readBuffer, 0, sizeof(uint)); if (!readSuccessful(n, sizeof(uint))) { return; } uint PID = BitConverter.ToUInt32(readBuffer, 0); Console.WriteLine("PID: {0}", PID); // Switch sul tipo di modifica switch (ModificationType) { // CASO 0: Aggiunta di una nuova applicazione case 0: // Lettura della lunghezza del nome dell'applicazione n = Stream.Read(readBuffer, 0, sizeof(int)); if (!readSuccessful(n, sizeof(uint))) { return; } // Conversione della lunghezza del nome in ordine dell'host int conv_length = BitConverter.ToInt32(readBuffer, 0); Console.WriteLine("Lunghezza convertita: {0}", conv_length); int NameLength = IPAddress.NetworkToHostOrder(conv_length); Console.WriteLine("Lunghezza nome: {0}", NameLength); Byte[] NameBuffer = new Byte[NameLength]; String AppName = String.Empty; // Lettura del nome dell'applicazione n = Stream.Read(NameBuffer, 0, NameLength); if (!readSuccessful(n, NameLength)) { return; } try { // Conversione in stringa AppName = System.Text.UnicodeEncoding.Unicode.GetString(NameBuffer); AppName = AppName.Replace("\0", String.Empty); } catch (ArgumentException) { AppName = "Nessun nome"; } Console.WriteLine("Nome dell'applicazione: {0}", AppName); // Lettura della lunghezza dell'icona n = Stream.Read(readBuffer, 0, sizeof(int)); if (!readSuccessful(n, sizeof(uint))) { return; } AppItem app = new AppItem(Item.ServerTab.MainWndw.DefaultIcon); app.PID = PID; app.Name = AppName; int conv_icon = BitConverter.ToInt32(readBuffer, 0); int IconLength = IPAddress.HostToNetworkOrder(conv_icon); Console.WriteLine("Lunghezza dell'icona: {0}", IconLength); // Se la dimensione è valida la si sostituisce a quella di default if (IconLength != 0 && IconLength < 1048576) { Console.WriteLine("Icona valida trovata"); // Lettura dell'icona dallo stream in blocchi da 1024 byte Byte[] BufferIcon = new Byte[IconLength]; int TotalRead = 0; int ToRead = 1024; while (TotalRead != IconLength) { if (ToRead > IconLength - TotalRead) { ToRead = IconLength - TotalRead; } n = Stream.Read(BufferIcon, TotalRead, ToRead); if (n == 0) { Console.WriteLine("Connessione persa durante la lettura dell'icona"); return; } TotalRead += n; } if (TotalRead != IconLength) { Console.WriteLine("Si è verificato un errore durante la lettura dell'icona"); Item.ServerTab.MainWndw.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { Item.ServerTab.MainWndw.CloseTab(Item.ServerTab); })); } unsafe { fixed(byte *buffer = &BufferIcon[0]) { IntPtr Hicon = CreateIconFromResourceEx((IntPtr)buffer, (uint)IconLength, 1, 0x00030000, 48, 48, 0); if (Hicon != null) { BitmapFrame bitmap = BitmapFrame.Create(Imaging.CreateBitmapSourceFromHIcon(Hicon, new Int32Rect(0, 0, 48, 48), BitmapSizeOptions.FromEmptyOptions())); if (bitmap.CanFreeze) { bitmap.Freeze(); app.Icon = bitmap; } DestroyIcon(Hicon); } } } } // Aggiunta di una nuova applicazione e notifica del cambiamento nella lista Item.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { lock (Item.Applications) { Item.Applications.Add(app); } })); Item.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { Item.ApplistRerrangeView(Item.Applist, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, app)); })); break; // Caso 1: rimozione di un'applicazione case 1: Console.WriteLine("Modifica: Rimozione"); // Rimozione dell'applicazione dalla lista Monitor.Enter(Item.Applications); foreach (AppItem appItem in Item.Applications) { if (appItem.PID == PID) { Console.WriteLine("Rimozione applicazione: {0}", appItem.Name); Monitor.Exit(Item.Applications); this.Item.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { lock (Item.Applications) { this.Item.Applications.Remove(appItem); } })); Monitor.Enter(Item.Applications); break; } } Monitor.Exit(Item.Applications); break; // Caso 3: cambio di focus case 2: Console.WriteLine("Modifica: Change Focus"); // Pulizia della selezione precedente this.Item.ServerTab.MainWndw.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { this.Item.Applist.SelectedItem = null; })); // Applicazione che perde il focus this.Item.ServerTab.MainWndw.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { // Aggiornamento lista app in foreground int index = this.Item.ServerTab.MainWndw.ForegroundApps.IndexOf(new ForegroundApp(Item.ServerTab.ForegroundApp, 0)); if (index != -1) { if (--this.Item.ServerTab.MainWndw.ForegroundApps[index].Count <= 0) { this.Item.ServerTab.MainWndw.ForegroundApps.RemoveAt(index); } } })); // Ricerca delle applicazioni coinvolte nel cambiamento Monitor.Enter(Item.Applications); foreach (AppItem appItem in Item.Applications) { // Applicazione che guadagna il focus if (appItem.PID == PID) { Console.WriteLine("Pid: {0} - applicazione: {1}", PID, appItem.Name); Monitor.Exit(Item.Applications); this.Item.ServerTab.MainWndw.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { lock (Item.Applications) { // Evidenziazione elemento nella tab appItem.HasFocus = true; this.Item.Applist.SelectedItem = appItem; this.Item.ServerTab.ForegroundApp = appItem.Name; // Aggiornamento lista delle app in foreground int index = this.Item.ServerTab.MainWndw.ForegroundApps.IndexOf(new ForegroundApp(appItem.Name, 0)); if (index != -1) { this.Item.ServerTab.MainWndw.ForegroundApps[index].Count++; } else { ForegroundApp newapp = new ForegroundApp(appItem.Name, 1); this.Item.ServerTab.MainWndw.ForegroundApps.Add(newapp); if (!this.Item.ServerTab.MainWndw.ForegroundAppsBox.IsEnabled) { this.Item.ServerTab.MainWndw.ForegroundAppsBox.SelectedItem = newapp; } } } })); Monitor.Enter(Item.Applications); } else if (appItem.HasFocus) { appItem.HasFocus = false; } } Monitor.Exit(Item.Applications); // Aggiornamento delle percentuali Item.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() => { Item.PercentageRefresh(); })); break; case 3: break; default: Console.WriteLine("Modifica sconosciuta"); break; } } Console.WriteLine("Thread - terminata ricezione dati dal server"); } catch (NullReferenceException) { ExceptionHandler.ReceiveConnectionError(Item); } catch (IOException) { ExceptionHandler.ReceiveConnectionError(Item); } catch (ObjectDisposedException) { ExceptionHandler.ReceiveConnectionError(Item); } catch (ArgumentOutOfRangeException) { ExceptionHandler.ReceiveConnectionError(Item); } catch (OutOfMemoryException) { ExceptionHandler.MemoryError(Item.ServerTab.MainWndw); } }