using System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; using SbLauncher; public static class UiStress { [STAThread] public static int Main() { var app = new Application(); app.ShutdownMode = ShutdownMode.OnExplicitShutdown; var sourceRoot = AppDomain.CurrentDomain.BaseDirectory; var dataRoot = Environment.GetEnvironmentVariable("SB_STRESS_ROOT"); if (string.IsNullOrEmpty(dataRoot)) dataRoot = sourceRoot; var window = (Window)XamlReader.Parse(File.ReadAllText(Path.Combine(sourceRoot, "Ui.xaml"))); var vm = new MainVm(); window.DataContext = vm; vm.ThemeApplier = delegate(string theme) { Theme.Apply(window, theme); }; vm.Load(new Paths(dataRoot)); vm.SetTheme(Theme.Dark); // Подключаем переходы вкладок без сетевых действий основного Wire. typeof(SbLauncher.App).GetMethod("WireTabs", BindingFlags.Static | BindingFlags.NonPublic) .Invoke(null, new object[] { window, vm }); var stopwatch = Stopwatch.StartNew(); long previous = 0, longest = 0; int ticks = 0; bool cleared = false; var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(50) }; timer.Tick += delegate { long now = stopwatch.ElapsedMilliseconds; if (previous != 0) longest = Math.Max(longest, now - previous); previous = now; ticks++; vm.ShowSettings = !vm.ShowSettings; vm.SetTheme(ticks % 2 == 0 ? Theme.Dark : Theme.Light); // Оставляем каждую фазу на несколько кадров, чтобы реально // проверить запуск и остановку Storyboard при нагрузке. if (ticks % 10 == 0) vm.ConnectionPhase = new[] { "connecting", "connected", "disconnecting", "idle" }[(ticks / 10) % 4]; if (ticks == 32 && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SB_STRESS_SCREENSHOT"))) { vm.SetTheme(Theme.Light); Capture(window, Environment.GetEnvironmentVariable("SB_STRESS_SCREENSHOT")); } if (ticks == 20) { vm.ClearLogCommand.Execute(null); cleared = vm.LogText.Length == 0; } if (now >= 5000) { timer.Stop(); app.Shutdown(); } }; window.Show(); timer.Start(); Task.Run(delegate { for (int i = 0; i < 20000; i++) vm.AppendLog("stress line " + i); }); app.Run(); vm.DisposeTimers(); Console.WriteLine("UI ticks: " + ticks + ", max interval: " + longest + " ms, log length: " + vm.LogText.Length + ", clear: " + cleared); return ticks >= 30 && longest < 500 && vm.LogText.Length <= 50000 && cleared ? 0 : 1; } static void Capture(Window window, string path) { window.UpdateLayout(); var bmp = new RenderTargetBitmap((int)window.Width, (int)window.Height, 96, 96, PixelFormats.Pbgra32); bmp.Render((Visual)window.Content); var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bmp)); using (var stream = new FileStream(path, FileMode.Create)) encoder.Save(stream); } }