Advertisement
Guest User

Untitled

a guest
Sep 8th, 2017
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.55 KB | None | 0 0
  1. App.xaml стандартный.
  2.  
  3. App.xaml.cs:
  4.  
  5. using System;
  6. using System.Windows;
  7.  
  8. namespace HangApp
  9. {
  10. public partial class App : Application
  11. {
  12. FreezeWatcher fw;
  13. protected override void OnStartup(StartupEventArgs e)
  14. {
  15. base.OnStartup(e);
  16. fw = new FreezeWatcher(TimeSpan.FromSeconds(5));
  17. fw.MainThreadHangs += OnHang;
  18. }
  19.  
  20. void OnHang(object sender, EventArgs e)
  21. {
  22. MessageBox.Show("Вы зависли, ха-ха! Прощайте.", "Ашипка");
  23. Environment.Exit(1);
  24. }
  25.  
  26. protected override void OnExit(ExitEventArgs e)
  27. {
  28. fw.MainThreadHangs -= OnHang;
  29. fw.Dispose();
  30. base.OnExit(e);
  31. }
  32. }
  33. }
  34.  
  35. FreezeWatcher.cs:
  36.  
  37. using System;
  38. using System.Threading;
  39. using System.Threading.Tasks;
  40. using System.Windows;
  41. using Microsoft.Win32;
  42.  
  43. namespace HangApp
  44. {
  45. public class FreezeWatcher : IDisposable
  46. {
  47. public FreezeWatcher(TimeSpan? pingTimeout = null, TimeSpan? checkTimeout = null)
  48. {
  49. if (!Application.Current.Dispatcher.CheckAccess())
  50. throw new InvalidOperationException("Must be constructed in main application thread");
  51. if (pingTimeout != null)
  52. {
  53. this.pingTimeout = pingTimeout.Value;
  54. this.checkTimeout = checkTimeout ?? pingTimeout.Value;
  55. }
  56.  
  57. mainTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
  58. mainTask = Task.Run(Run);
  59. }
  60.  
  61. async Task Run()
  62. {
  63. try
  64. {
  65. await LoopChecks(cancellationTokenSource.Token);
  66. }
  67. catch (OperationCanceledException)
  68. {
  69. /* do nothing, cancellation is expected */
  70. }
  71. }
  72.  
  73. async Task LoopChecks(CancellationToken ct)
  74. {
  75. try
  76. {
  77. SystemEvents.PowerModeChanged += OnPowerModeChanged;
  78. while (true)
  79. {
  80. await Task.Delay(checkTimeout, ct);
  81. PowerStateChanged = false;
  82. var pingSuccess = await Check(ct);
  83. if (!pingSuccess && !PowerStateChanged)
  84. {
  85. OnHang();
  86. await Unhung(ct);
  87. OnUnhang();
  88. }
  89. }
  90. }
  91. finally
  92. {
  93. SystemEvents.PowerModeChanged -= OnPowerModeChanged;
  94. }
  95. }
  96.  
  97. void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
  98. {
  99. PowerStateChanged = true;
  100. }
  101.  
  102. async Task<bool> Check(CancellationToken ct)
  103. {
  104. var ping = PingMain(ct);
  105. var delay = Task.Delay(pingTimeout, ct);
  106. var succeeded = (await Task.WhenAny(ping, delay)) == ping;
  107. ct.ThrowIfCancellationRequested();
  108. return succeeded;
  109. }
  110.  
  111. Task Unhung(CancellationToken ct)
  112. {
  113. return PingMain(ct);
  114. }
  115.  
  116. Task PingMain(CancellationToken ct)
  117. {
  118. return Task.Factory.StartNew(
  119. () => { /* nothing */ },
  120. ct,
  121. TaskCreationOptions.PreferFairness,
  122. mainTaskScheduler);
  123. }
  124.  
  125. void OnHang() => MainThreadHangs?.Invoke(this, new EventArgs());
  126. void OnUnhang() => MainThreadUnhangs?.Invoke(this, new EventArgs());
  127.  
  128. public void Dispose()
  129. {
  130. if (isDisposed)
  131. return;
  132. isDisposed = true;
  133.  
  134. cancellationTokenSource.Cancel();
  135. mainTask.Wait();
  136. }
  137.  
  138. public event EventHandler<EventArgs> MainThreadHangs;
  139. public event EventHandler<EventArgs> MainThreadUnhangs;
  140.  
  141. TaskScheduler mainTaskScheduler;
  142. TimeSpan pingTimeout = TimeSpan.FromSeconds(30);
  143. TimeSpan checkTimeout = TimeSpan.FromSeconds(30);
  144.  
  145. Task mainTask;
  146. CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
  147. bool isDisposed = false;
  148.  
  149. object powerStateMutex = new object();
  150. bool powerStateChanged = false;
  151. bool PowerStateChanged
  152. {
  153. get { lock (powerStateMutex) return powerStateChanged; }
  154. set { lock (powerStateMutex) powerStateChanged = value; }
  155. }
  156. }
  157. }
  158.  
  159. MainWindow.xaml:
  160.  
  161. <Window x:Class="HangApp.MainWindow"
  162. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  163. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  164. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  165. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  166. xmlns:local="clr-namespace:HangApp"
  167. mc:Ignorable="d"
  168. Title="Test" Height="350" Width="525">
  169. <Grid>
  170. <Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="100" Click="DoHang">Freeze</Button>
  171. </Grid>
  172. </Window>
  173.  
  174. MainWindow.xaml.cs:
  175.  
  176. using System.Windows;
  177.  
  178. namespace HangApp
  179. {
  180. public partial class MainWindow : Window
  181. {
  182. public MainWindow()
  183. {
  184. InitializeComponent();
  185. }
  186.  
  187. void DoHang(object sender, RoutedEventArgs e)
  188. {
  189. new System.Threading.Semaphore(0, 1).WaitOne();
  190. }
  191. }
  192. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement