static Tuple <Int64, TimeSpan> Test(ITest test, Int32 threads, Int32 runsPerThread, IPEndPoint endpoint) { Int64 counter = 0; test.Init(endpoint, CancellationToken.None).Wait(); var cancel = new CancellationTokenSource(); var threadLists = new List <Thread>(); var total = threads * runsPerThread; var progress = 0; var bars = 0; var sw = new Stopwatch(); Console.WriteLine(); sw.Start(); Exception error = null; for (int i = 0; i < threads; i++) { int ii = i; var ts = new ThreadStart(() => { try { for (int r = 0; r < runsPerThread; r++) { test.RunClient(ii, cancel.Token).Wait(); Interlocked.Increment(ref counter); var p = Interlocked.Increment(ref progress); var percentage = (Int32)((p * 100D) / total); while (bars < percentage) { Interlocked.Increment(ref bars); Console.Write("|"); } } } catch (Exception ex) { Console.Write("[E." + test.GetType().Name + ", " + ex.GetType().Name + ":" + ex.Message + "]"); Interlocked.CompareExchange(ref error, ex, null); } }); var t = new Thread(ts); t.Start(); threadLists.Add(t); } foreach (var t in threadLists) { t.Join(); } sw.Stop(); cancel.Cancel(); test.ClearData(); if (error != null) { return(null); } else { return(new Tuple <Int64, TimeSpan>(counter, sw.Elapsed)); } }