C# 优雅地处理异常的问题
我正在开发一个应用程序,它使用NAudio将麦克风的输入记录到.wav文件中。我的Recorder类使用BackgroundWorker进行录制。我开始录制并一直录制,直到10秒过去,或者用户请求取消。这在大多数情况下都很好,只有一种情况除外。在调试中,当我中途拔下录音设备时,一切都没有进展。我希望在BackgroundWorkedCompletedTask方法中,如果worker完成事件args为e.Error(如果我抛出任何标准异常,这可以正常工作),就会发现问题,但事实并非如此。当我选择“全部中断”时,它会将我带到BackgroundWorkedCompletedTask方法,在C# 优雅地处理异常的问题,c#,exception,C#,Exception,我正在开发一个应用程序,它使用NAudio将麦克风的输入记录到.wav文件中。我的Recorder类使用BackgroundWorker进行录制。我开始录制并一直录制,直到10秒过去,或者用户请求取消。这在大多数情况下都很好,只有一种情况除外。在调试中,当我中途拔下录音设备时,一切都没有进展。我希望在BackgroundWorkedCompletedTask方法中,如果worker完成事件args为e.Error(如果我抛出任何标准异常,这可以正常工作),就会发现问题,但事实并非如此。当我选择“
this.waveIn.StopRecording()行代码>,并且对象上的所有属性显示为无法计算表达式,因为本机帧位于调用堆栈的顶部。
我假设这与NAudio使用非托管代码与设备交互有关;我希望你能就如何处理这种情况提供指导或建议。在这里,try/catch块似乎不起作用,那么我应该在哪里处理它呢?提前感谢您的帮助
为完整起见,以下是涉及的代码的两个相关部分:
private void RecordUsingBackgroundWorker(BackgroundWorker worker)
{
var devices = this.FindDevices();
var deviceIndex = devices.IndexOf(this.requestedDevice);
var waveIn = new WaveIn(WaveCallbackInfo.FunctionCallback());
waveIn.DeviceNumber = deviceIndex;
waveIn.WaveFormat = new WaveFormat(8000, 1);
this.waveIn = waveIn;
this.waveIn.DataAvailable += new EventHandler<WaveInEventArgs>(DataIsAvailable);
var filename = Globals.ThisAddIn.CommentFilePath;
this.waveFileWriter = new WaveFileWriter(filename, waveIn.WaveFormat);
var stopwatch = new Stopwatch();
stopwatch.Start();
this.waveIn.StartRecording();
while (stopwatch.ElapsedMilliseconds < 10000 && !worker.CancellationPending)
{
}
}
如果对StopRecording的调用被阻塞,一个选项是将其包装在异步调用中,并等待其完成,并超时:
public bool WaitFor(Action action, TimeSpan timeout)
{
var waitHandle = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(state =>
{
action();
waitHandle.Set();
});
return waitHandle.WaitOne(timeout);
}
您可以这样使用它:
if (!WaitFor(this.waveIn.StopRecording, TimeSpan.FromSeconds(2)))
throw new TimeoutException("Timed out waiting for recording to stop");
请注意,这会使线程池线程在超时的操作上被阻塞,因此您可能需要调用一个API方法来取消挂起的操作(如果存在),或者应该礼貌地继续关闭应用程序(因为您的线程处于暂停状态,应用程序状态可能会受到影响)在实际的生产场景中,最好进一步改进此方法,以便在超时后任务是否完成时获得肯定的确认(如果您可以调用某种形式的取消,则此方法非常有用)。Hmya,我以前见过NAudio的类似问题。它使用mmsystem的方式使得死锁非常常见。不太确定它应该受到责备,它以文档化的方式使用API。这只是一种很少受到考验的方式。音频驱动程序也是一个常见的麻烦源,激烈的竞争似乎没有给一个好的软件工程师留下多少钱
当设备在使用时拔下插头总是一个问题,就像在写入时将闪存驱动器从USB插槽中拔出一样。或者在端口打开时拔下USB串行端口模拟器。在使用设备时拔掉设备插头的冲动似乎是不可抗拒的。尽管他们在尝试了几次之后会对它感到厌烦
也许Larry Osterman有一些意见,他在音频层做了很多工作。他在这里发帖,你可以在他的博客上留言,引导他回答这个问题。除此之外,您还需要找到一种方法让NAudio作者与Microsoft支持部门合作。或者自己解决这个问题,提供源代码是有原因的。祝你好运
if (!WaitFor(this.waveIn.StopRecording, TimeSpan.FromSeconds(2)))
throw new TimeoutException("Timed out waiting for recording to stop");