关于使用NAudio麦克风扬声器组件造成WPF应用程序卡死问题跟踪及异步队列的 ...

打印 上一主题 下一主题

主题 918|帖子 918|积分 2754

由于WPF应用程序出现卡死的情况,特记录一下问题的跟踪情况
1、多次进行NAudio事件注册,没有启用注销再注册的方式,造成应用程序CPU过高
private AudioNotificationClient audioNotification = new AudioNotificationClient();
audioNotification.DeviceStateChanged += AudioNotification_DeviceStateChanged;
private MMDeviceEnumerator _mmDeviceEnumerator = new MMDeviceEnumerator();
_mmDeviceEnumerator.RegisterEndpointNotificationCallback(audioNotification);
缺少注销
_mmDeviceEnumerator.UnregisterEndpointNotificationCallback(audioNotification);
2、事件注册同时麦克风设备状态发生改变DeviceStateChanged,造成线程死锁
可以使用异步队列,把事件的注册,注销与DeviceStateChanged执行逻辑都放进异步队列,保证不会出现同时执行的情况。
异步队列的实现:
  1. /// <summary>
  2.     /// 异步任务队列
  3.     /// </summary>
  4.     public class AsyncTaskQueue : IDisposable
  5.     {
  6.         private bool _isDisposed;
  7.         private readonly ConcurrentQueue<AwaitableTask> _queue = new ConcurrentQueue<AwaitableTask>();
  8.         private Thread _thread;
  9.         private AutoResetEvent _autoResetEvent;
  10.         /// <summary>
  11.         /// 异步任务队列
  12.         /// </summary>
  13.         public AsyncTaskQueue()
  14.         {
  15.             _autoResetEvent = new AutoResetEvent(false);
  16.             _thread = new Thread(InternalRuning) {IsBackground = true};
  17.             _thread.Start();
  18.         }
  19.         private bool TryGetNextTask(out AwaitableTask task)
  20.         {
  21.             task = null;
  22.             while (_queue.Count > 0)
  23.             {
  24.                 if (_queue.TryDequeue(out task) && (!AutoCancelPreviousTask || _queue.Count == 0)) return true;
  25.                 task.Cancel();
  26.             }
  27.             return false;
  28.         }
  29.         private AwaitableTask PenddingTask(AwaitableTask task)
  30.         {
  31.             lock (_queue)
  32.             {
  33.                 Debug.Assert(task != null);
  34.                 _queue.Enqueue(task);
  35.                 _autoResetEvent.Set();
  36.             }
  37.             return task;
  38.         }
  39.         private void InternalRuning()
  40.         {
  41.             while (!_isDisposed)
  42.             {
  43.                 if (_queue.Count == 0)
  44.                 {
  45.                     _autoResetEvent.WaitOne();
  46.                 }
  47.                 while (TryGetNextTask(out var task))
  48.                 {
  49.                     if (task.IsCancel) continue;
  50.                     if (UseSingleThread)
  51.                     {
  52.                         task.RunSynchronously();
  53.                     }
  54.                     else
  55.                     {
  56.                         task.Start();
  57.                     }
  58.                 }
  59.             }
  60.         }
  61.         /// <summary>
  62.         /// 是否使用单线程完成任务.
  63.         /// </summary>
  64.         public bool UseSingleThread { get; set; } = true;
  65.         /// <summary>
  66.         /// 自动取消以前的任务。
  67.         /// </summary>
  68.         public bool AutoCancelPreviousTask { get; set; } = false;
  69.         /// <summary>
  70.         /// 执行任务
  71.         /// </summary>
  72.         /// <param name="action"></param>
  73.         /// <returns></returns>
  74.         public AwaitableTask Run(Action action)
  75.             => PenddingTask(new AwaitableTask(new Task(action, new CancellationToken(false))));
  76.         /// <summary>
  77.         /// 执行任务
  78.         /// </summary>
  79.         /// <typeparam name="TResult"></typeparam>
  80.         /// <param name="function"></param>
  81.         /// <returns></returns>
  82.         public AwaitableTask<TResult> Run<TResult>(Func<TResult> function)
  83.             => (AwaitableTask<TResult>) PenddingTask(new AwaitableTask<TResult>(new Task<TResult>(function)));
  84.         /// <inheritdoc />
  85.         public void Dispose()
  86.         {
  87.             Dispose(true);
  88.             GC.SuppressFinalize(this);
  89.         }
  90.         
  91.         /// <summary>
  92.         /// 析构任务队列
  93.         /// </summary>
  94.         ~AsyncTaskQueue() => Dispose(false);
  95.         private void Dispose(bool disposing)
  96.         {
  97.             if (_isDisposed) return;
  98.             if (disposing)
  99.             {
  100.                 _autoResetEvent.Dispose();
  101.             }
  102.             _thread = null;
  103.             _autoResetEvent = null;
  104.             _isDisposed = true;
  105.         }
  106.         /// <summary>
  107.         /// 可等待的任务
  108.         /// </summary>
  109.         public class AwaitableTask
  110.         {
  111.             private readonly Task _task;
  112.             /// <summary>
  113.             /// 初始化可等待的任务。
  114.             /// </summary>
  115.             /// <param name="task"></param>
  116.             public AwaitableTask(Task task) => _task = task;
  117.             /// <summary>
  118.             /// 任务的Id
  119.             /// </summary>
  120.             public int TaskId => _task.Id;
  121.             /// <summary>
  122.             /// 任务是否取消
  123.             /// </summary>
  124.             public bool IsCancel { get; private set; }
  125.             /// <summary>
  126.             /// 开始任务
  127.             /// </summary>
  128.             public void Start() => _task.Start();
  129.             /// <summary>
  130.             /// 同步执行开始任务
  131.             /// </summary>
  132.             public void RunSynchronously() => _task.RunSynchronously();
  133.             /// <summary>
  134.             /// 取消任务
  135.             /// </summary>
  136.             public void Cancel() => IsCancel = true;
  137.             /// <summary>
  138.             /// 获取任务等待器
  139.             /// </summary>
  140.             /// <returns></returns>
  141.             public TaskAwaiter GetAwaiter() => new TaskAwaiter(this);
  142.             /// <summary>Provides an object that waits for the completion of an asynchronous task. </summary>
  143.             [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true, Synchronization = true)]
  144.             public struct TaskAwaiter : INotifyCompletion
  145.             {
  146.                 private readonly AwaitableTask _task;
  147.                 /// <summary>
  148.                 /// 任务等待器
  149.                 /// </summary>
  150.                 /// <param name="awaitableTask"></param>
  151.                 public TaskAwaiter(AwaitableTask awaitableTask) => _task = awaitableTask;
  152.                 /// <summary>
  153.                 /// 任务是否完成.
  154.                 /// </summary>
  155.                 public bool IsCompleted => _task._task.IsCompleted;
  156.                 /// <inheritdoc />
  157.                 public void OnCompleted(Action continuation)
  158.                 {
  159.                     var This = this;
  160.                     _task._task.ContinueWith(t =>
  161.                     {
  162.                         if (!This._task.IsCancel) continuation?.Invoke();
  163.                     });
  164.                 }
  165.                 /// <summary>
  166.                 /// 获取任务结果
  167.                 /// </summary>
  168.                 public void GetResult() => _task._task.Wait();
  169.             }
  170.         }
  171.         /// <summary>
  172.         /// 可等待的任务
  173.         /// </summary>
  174.         /// <typeparam name="TResult"></typeparam>
  175.         public class AwaitableTask<TResult> : AwaitableTask
  176.         {
  177.             /// <summary>
  178.             /// 初始化可等待的任务
  179.             /// </summary>
  180.             /// <param name="task">需要执行的任务</param>
  181.             public AwaitableTask(Task<TResult> task) : base(task) => _task = task;
  182.             private readonly Task<TResult> _task;
  183.             /// <summary>
  184.             /// 获取任务等待器
  185.             /// </summary>
  186.             /// <returns></returns>
  187.             public new TaskAwaiter GetAwaiter() => new TaskAwaiter(this);
  188.             /// <summary>
  189.             /// 任务等待器
  190.             /// </summary>
  191.             [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true, Synchronization = true)]
  192.             public new struct TaskAwaiter : INotifyCompletion
  193.             {
  194.                 private readonly AwaitableTask<TResult> _task;
  195.                 /// <summary>
  196.                 /// 初始化任务等待器
  197.                 /// </summary>
  198.                 /// <param name="awaitableTask"></param>
  199.                 public TaskAwaiter(AwaitableTask<TResult> awaitableTask) => _task = awaitableTask;
  200.                 /// <summary>
  201.                 /// 任务是否已完成。
  202.                 /// </summary>
  203.                 public bool IsCompleted => _task._task.IsCompleted;
  204.                 /// <inheritdoc />
  205.                 public void OnCompleted(Action continuation)
  206.                 {
  207.                     var This = this;
  208.                     _task._task.ContinueWith(t =>
  209.                     {
  210.                         if (!This._task.IsCancel) continuation?.Invoke();
  211.                     });
  212.                 }
  213.                 /// <summary>
  214.                 /// 获取任务结果。
  215.                 /// </summary>
  216.                 /// <returns></returns>
  217.                 public TResult GetResult() => _task._task.Result;
  218.             }
  219.         }
复制代码
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表