Preferirei evitare la riesumazione di vecchio codice. Provo quasi disgusto quando, aprendo un progetto con la versione installata di Visual Studio, viene richiesta la conversione del progetto per questa versione. next, next con la speranza che alla fine della procedura non vengano visualizzati strani errori. Il progetto in questione era un tool che connettendosi ad un server scaricava in un formato accessibile uno o più stream di dati proprietari. Scendendo nel dettaglio del puro codice, non era altro che una console application che, leggendo un file di configurazione, si connetteva ad un server remoto avviando uno o più thread, uno per ogni stream di dati, per il download e il salvataggio di dati. Funzionava. Mettere le mani ad una applicazione che funziona solo per farla funzionare meglio potrebbe portare due possibili conclusioni: ottenere l'effetto voluto con prestazioni migliori e/o consumo di risorse inferiore, oppure fare crollare tutta la delicata impalcatura che permetteva il funzionamento corretto dell'applicativo e dover poi tornare alla versione precedente - solo in questo caso è meglio restare in silenzio che passare per idioti.Il mio intento era ovviamente il primo. Il tutto funzionava in modo semplice, come detto: per ogni connessione richiesta aprivo un nuovo thread. E' questa la strada migliore giusta a questa evoluzione del framework .net? Assolutamente no visto che la creazione di thread ha un certo peso sia per la cpu che per il consumo di risorse. Partendo dall'inizio per rendere il tutto più comprensibile qui di seguito un esempio che, all'opposto di quello che mi ha ispirato per l'approfondimento, non cercherà di eseguire le connessioni su un server, ma sarà lui a poter ricevere un numero pressoché infinito di richieste in entrata. Ecco la prima versione del codice:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net; using System.Net.Sockets; using System.Threading; namespace Server2 { class Program { static void Main(string[] args) { List<Thread> coll = new List<Thread>(); TcpListener listnet = new TcpListener(IPAddress.Any, 4001); listnet.Start(); Console.WriteLine("Wait connection..."); while (true) { TcpClient client = listnet.AcceptTcpClient(); Thread th = new Thread(Accept); coll.Add(th); th.Start(client); } } static void Accept(object clientObject) { using (TcpClient client = (TcpClient)clientObject) using (NetworkStream n = client.GetStream()) { while (true) { string requestText = string.Empty; while (true) { byte[] data = new byte[1000]; int byteRead = n.Read(data, 0, data.Length); requestText += System.Text.Encoding.Default.GetString(data, 0, byteRead); if (requestText.EndsWith("\r\n")) break; } if (requestText.Trim().ToLower() == "quit") break; byte[] returnText = System.Text.Encoding.Default.GetBytes("ciao " + requestText); n.Write(returnText, 0, returnText.Length); n.Flush(); } } } } }
static void Main(string[] args) { ThreadPool.SetMaxThreads(50, 50); // <- aumentare il numero in caso ThreadPool.SetMinThreads(50, 50); // <- minimo di thread creati TcpListener listnet = new TcpListener(IPAddress.Any, 4000); listnet.Start(); while (true) { TcpClient client = listnet.AcceptTcpClient(); ThreadPool.QueueUserWorkItem(Accept, client); } }
ThreadPool.SetMaxThreads(50, 50);
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net; using System.Net.Sockets; using System.Threading; namespace Server3 { class Program { static void Main(string[] args) { TcpListener listnet = new TcpListener(IPAddress.Any, 4002); listnet.Start(); Console.WriteLine("Wait connection3..."); while (true) { TcpClient client = listnet.AcceptTcpClient(); new MyEcho().Begin(client, null, null); } } } public class MyEcho : IAsyncResult { TcpClient _client; NetworkStream _stream; object _userState; ManualResetEvent _waitHandle = new ManualResetEvent(false); int _bytesRead = 0; byte[] _data = new byte[10000]; Exception _exception; internal MyEcho() { } public object AsyncState { get { return _userState; } } public WaitHandle AsyncWaitHandle { get { return _waitHandle; } } public bool CompletedSynchronously { get { return false; } } public bool IsCompleted { get { return _waitHandle.WaitOne(0, false); } } internal void Begin(TcpClient c, AsyncCallback callback, object state) { _client = c; _userState = state; _stream = _client.GetStream(); Task.Factory.StartNew(Read).ContinueWith(ant => { _exception = ant.Exception; if (_stream != null) { try { _stream.Close(); } catch (Exception ex) { _exception = ex; } _waitHandle.Set(); if (callback != null) callback(this); } }, TaskContinuationOptions.OnlyOnFaulted); } internal byte[] End() { AsyncWaitHandle.WaitOne(); if (_exception!=null) throw _exception; return _data; } void Read() { Task<int> readChunck = Task<int>.Factory.FromAsync( _stream.BeginRead, _stream.EndRead, _data, _bytesRead,_data.Length-_bytesRead, null); readChunck.ContinueWith(ContinueRead, TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.AttachedToParent); } void ContinueRead(Task<int> readChunk) { _bytesRead += readChunk.Result; string requestText = System.Text.Encoding.Default.GetString(_data, 0, _bytesRead); if (!requestText.EndsWith("\r\n")) { Read(); return; } byte[] returnText = System.Text.Encoding.Default.GetBytes("ciao3 " + requestText); Task.Factory.FromAsync(_stream.BeginWrite, _stream.EndWrite, returnText, 0, returnText.Length, null); _bytesRead = 0; if (requestText.Trim().ToLower() != "quit") { Read(); } else { _stream.Dispose(); } } } }
TcpClient client = listnet.AcceptTcpClient(); new MyEcho().Begin(client, null, null);
Task.Factory.StartNew(Read).ContinueWith(ant => { ...
Task<int>[] tasks = new Task<int>[2]; tasks[0] = new Task<int>(() => { // Do some work... return 34; }); tasks[1] = new Task<int>(() => { // Do some work... return 8; }); var continuation = Task.Factory.ContinueWhenAll( tasks, (antecedents) => { int answer = tasks[0].Result + tasks[1].Result; Console.WriteLine("The answer is {0}", answer); }); tasks[0].Start(); tasks[1].Start(); continuation.Wait();
Task.Factory.StartNew(myFunction).ContinueWith(ant => {...ok...},TaskContinuationOptions.OnlyOnFaulted); Task.Factory.StartNew(myFunction).ContinueWith(ant => {...Error...},TaskContinuationOptions.OnlyOnFaulted);
Task<int> readChunck = Task<int>.Factory.FromAsync( _stream.BeginRead, _stream.EndRead, _data, _bytesRead,_data.Length-_bytesRead, null);
public virtual IAsyncResult BeginWrite( byte[] buffer, int offset, int count, AsyncCallback callback, Object state )
void First() { int result=Calc(12); Console.WriteLine(result); } int Calc(int i) { return i*i; }
async Task First() { int result= await Calc(12); Console.WriteLine(result); } async Task<int> Calc(int i) { return i*i; }
async Task First() { int result = 0; Task<int> result2 = Calc(12); Console.Write("Before"); result=await result2; Console.WriteLine(":: "+result); } async Task<int> Calc(int i) { await Task.Delay(1000); return i * i; }
Task<int> result2 = Calc(12); Task<int> result3 = Calc(13); Console.Write("Before"); result=await result2; resultx=await result3; // oppure: int[] results=await Task.WhenAll(result2, result3);
using (StreamReader reader = File.OpenText(filename)) { result = new char[reader.BaseStream.Length]; await reader.ReadAsync(result, 0, (int)reader.BaseStream.Length); }
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace Server4 { class Program { static void Main(string[] args) { Task s = Start(); s.Wait(); } static async Task Start() { TcpListener listnet = new TcpListener(IPAddress.Any, 4003); listnet.Start(); Console.WriteLine("Wait connection4..."); while (true) { TcpClient client = await listnet.AcceptTcpClientAsync(); HandleConnectionAsync(client); } } private static async void HandleConnectionAsync(TcpClient client) { try { using (NetworkStream n = client.GetStream()) { while (true) { string requestText = string.Empty; while (true) { byte[] data = new byte[1000]; int byteRead = await n.ReadAsync(data, 0, data.Length); requestText += System.Text.Encoding.Default.GetString(data, 0, byteRead); if (requestText.EndsWith("\r\n")) break; } if (requestText.Trim().ToLower() == "quit") break; byte[] returnText = System.Text.Encoding.Default.GetBytes("ciaoAsync " + requestText); await n.WriteAsync(returnText, 0, returnText.Length); } } } catch (Exception) { } finally { client.Close(); } } } }
TcpClient client = await listnet.AcceptTcpClientAsync();
int byteRead = await n.ReadAsync(data, 0, data.Length); await n.WriteAsync(returnText, 0, returnText.Length);
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- Plinq in tram, il 25 maggio 2014 alle 22:18
- Disabilitare tutti i web control in una pagina?, l'8 luglio 2009 alle 14:21
- C# 4.0 Beta 1, quello che io ho visto, il 24 maggio 2009 alle 20:33