WMNetMgr.dll 应用程序错误 w3wp.exe 使用 WMPLib C# .NET 时出错
WMNetMgr.dll Application Error w3wp.exe error using WMPLib C# .NET
我的 Web 应用程序经常崩溃并重置 IIS 中的应用程序池,导致严重的性能问题,并且擦除我的应用程序中的所有计时线程 运行ning。
该站点是 .NET 4.5.2 C# MVC5 站点 运行 宁在 2012 Windows AWS 中的服务器 EC2 实例上。
这个问题是在我开始看到网站在 运行 几分钟后难以加载时第一次注意到的。我认为这可能是 ApplicationPool 回收,并确保在 IIS 中正确设置 IdleTime 和 Application Preload。问题仍然存在。
接下来我去服务器管理器检查事件日志,发现这些条目大约每 15 分钟发生一次:
Faulting application name: w3wp.exe, version: 8.5.9600.16384, time
stamp: 0x5215df96 Faulting module name: WMNetMgr.dll_unloaded,
version: 12.0.9600.17415, time stamp: 0x545047db Exception code:
0xc0000005 Fault offset: 0x00000000000cf5cf Faulting process id:
0x17d0 Faulting application start time: 0x01d331dc20f096d0 Faulting
application path: c:\windows\system32\inetsrv\w3wp.exe Faulting module
path: WMNetMgr.dll Report Id: 777a35de-9dd1-11e7-81d7-025ff0be916d
Faulting package full name: Faulting package-relative application ID:
和
WIN-7PCRJOFR05F 5011 Warning Microsoft-Windows-WAS System 9/20/2017
7:01:04 AM - A process serving application pool 'SiteName' suffered a
fatal communication error with the Windows Process Activation Service.
The process id was '6096'. The data field contains the error number.
接下来我运行一个DebugDiag2的收集与分析:
WARNING - DebugDiag was not able to locate debug symbols for
WMNetMgr.dll>, so the information below may be incomplete.
In
w3wp__SiteName__PID__5088__Date__09_20_2017__Time_06_31_02AM__436__Second_Chance_Exception_C0000005.dmp
an access violation exception (0xC0000005) occured on thread 26 when
another Module attempted to call the following unloaded Module:
WMNetMgr.dll>.
Thread 26:
Call Stack Unloaded_WMNetMgr.dll+cf5cf
0x000000de575cf7c0 0x000000dc
2ed5ec10
这是此调试器报告的唯一错误。在报告的 .NET 堆栈跟踪中没有其他异常。我似乎无法获得此特定 .dll 的调试符号,而且消息似乎也不是很有帮助。
该应用程序利用 WMPLib 在 wmplayer 启动时创建一个单例实例,以通过来自客户端的 Web 请求在 Windows Server 2012 实例上播放声音。该应用程序在这方面可以正常播放声音和来自多个用户的请求。
这是单例:
public sealed class SoundboardSingleton : IDisposable
{
private static readonly Lazy<SoundboardSingleton> lazy =
new Lazy<SoundboardSingleton>(() => new SoundboardSingleton());
public static SoundboardSingleton Instance { get { return lazy.Value; } }
public WindowsMediaPlayer WMPlayer;
private StayAliveBot _liveBot;
private Thread _botThread;
private SoundboardSingleton()
{
WMPlayer = new WindowsMediaPlayer();
WMPlayer.settings.volume = 50;
_liveBot = new StayAliveBot();
_botThread = new Thread(_liveBot.Live);
_botThread.Start();
}
public void Dispose()
{
if (_botThread.IsAlive)
{
_botThread.Abort();
}
}
}
public class StayAliveBot
{
public void Live()
{
while (SoundboardSingleton.Instance != null)
{
Thread.Sleep(1500000);
SoundboardHelper.PlaySound("C:\SoundboardOpFiles\TestTone.wav");
}
}
}
并最初在 Startup.cs 中通过以下方式实例化:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
// startup soundboard singleton
SoundboardSingleton.Instance.WMPlayer.settings.volume = 50;
}
}
我可以在我的本地开发机器上 运行 这个应用程序,没有任何问题或崩溃。一切都按预期运行,没有崩溃。在部署到 EC2 实例时,网站上的一切正常,但现在每 15 分钟就会发生一次崩溃/重置。
我的怀疑是:
A) WMPLib 实例存在问题,缺少对 Windows Server 2012 框的依赖,允许它播放声音但会定期导致崩溃。
B) 我在单例实例化时犯了一个错误,它以某种方式使我的应用程序崩溃。
我已经尝试了 here 的解决方案,但没有结果。
如有任何帮助,我们将不胜感激。
编辑:我已经确认问题与 WMPLib 的使用有关,因为删除它的使用停止了每 15 分钟一次的崩溃。仍然不确定为什么会这样。
这不是对您问题的直接回答,而是对同一件事的不同处理方式。尝试使用 WPF 中的线程安全 MediaPlayer class 而不是 WMPLib COM 控件。添加对 WindowsBase 和 PresentationCore 的引用,并改用如下内容:
using System.Windows.Media;
public void PlaySound(string filename)
{
var mplayer = new MediaPlayer();
mplayer.MediaEnded += new EventHandler(MediaEndedHandler);
mplayer.Open(new Uri(filename));
mplayer.Play();
}
public void MediaEndedHandler(object sender, EventArgs e)
{
((MediaPlayer)sender).Close();
}
您也可以像上面一样将它用作单例,并且它是完全线程安全的,而 WMPLib 则不是。
编辑:
如评论中所述,您真的可以只使用带有 public 布尔值 属性 的静态 class 来显示忙音。 IIS 中的静态 class 在应用程序的所有请求之间共享,并且 class 仅在回收应用程序池时受到垃圾收集,因此您需要注意对象的生命周期您存储在其中,以避免内存消耗问题。此代码将为每个 PlaySound() 使用媒体播放器 class 的新实例,并在播放结束后立即处理它,但忙标志在对服务器发出的所有请求中很常见。
using System;
using System.Threading;
using System.Windows.Media;
namespace SoundBoardApp
{
public static class Soundboard
{
private static bool _isBusy = false;
public static bool IsBusy { get { return _isBusy; } }
private static void MediaEndedHandler(object sender, EventArgs e)
{
_isBusy = false;
var wmp = ((MediaPlayer)sender);
wmp.MediaEnded -= new EventHandler(MediaEndedHandler);
wmp.Close();
}
public static bool PlaySound(string filename)
{
if (!_isBusy)
{
_isBusy = true;
var wmp = new MediaPlayer();
wmp.MediaEnded += new EventHandler(MediaEndedHandler);
wmp.Volume = 0.5;
wmp.Open(new Uri(filename));
wmp.Play();
return true;
}
else
{
return false;
}
}
}
public class StayAliveBot
{
public void Live()
{
while (true)
{
Thread.Sleep(1500000);
if (!Soundboard.IsBusy) Soundboard.PlaySound("C:\SoundboardOpFiles\TestTone.wav");
}
}
}
}
我最终使用 NAudio 和我的单例模式。
根据 Lex Li 的建议,我使用了第三方,因为 Windows.MediaPlayer 不适用于网络应用程序。基于 Drunken Code Monkey 的解决方案,我在单例上使用了一个布尔标志来评估播放状态,该状态由一个单独的线程经常检查,该线程评估单例中 IWavePlayer 对象上的 PlaybackState.Stopped 值。我唯一关心的是性能。我还没有注意到任何问题,但我敢肯定,如果甚至可以从 Web 应用程序来管理事件,那么在处理程序中管理事件的性能会更高,代码也会更少。
代码如下:
using NAudio.Wave;
public sealed class SoundboardSingleton : IDisposable
{
private static readonly Lazy<SoundboardSingleton> lazy =
new Lazy<SoundboardSingleton>(() => new SoundboardSingleton());
public static SoundboardSingleton Instance { get { return lazy.Value; } }
public IWavePlayer WaveOutDevice { get; set; }
public AudioFileReader AudioFileReaderObj { get; set; }
public float Volume { get; set; }
private MediaCloser _mediaCloser;
private Thread _mediaCloserThread;
private StayAliveBot _liveBot;
private Thread _botThread;
public bool IsBusy { get; set; }
private SoundboardSingleton()
{
// checks our NAudio WaveOutDevice playback for stop
_mediaCloser = new MediaCloser();
_mediaCloserThread = new Thread(_mediaCloser.CheckForStoppedPlayback);
_mediaCloserThread.Start();
// thread to play sound every 25 minutes, to avoid idle flag
_liveBot = new StayAliveBot();
_botThread = new Thread(_liveBot.Live);
_botThread.Start();
}
public bool PlaySound(string filename)
{
// make sure we are not active
if (IsBusy) { return false; }
// process sound
IsBusy = true;
WaveOutDevice = new WaveOutEvent();
AudioFileReaderObj = new AudioFileReader(filename);
AudioFileReaderObj.Volume = Volume;
WaveOutDevice.Init(AudioFileReaderObj);
WaveOutDevice.Play();
return true;
}
public void CloseWaveOut()
{
// clean up sound objects
WaveOutDevice?.Stop();
if (AudioFileReaderObj != null)
{
AudioFileReaderObj.Dispose();
AudioFileReaderObj = null;
}
if (WaveOutDevice != null)
{
WaveOutDevice.Dispose();
WaveOutDevice = null;
}
}
public void Dispose()
{
if (_mediaCloserThread.IsAlive)
{
_mediaCloserThread.Abort();
}
if (_botThread.IsAlive)
{
_botThread.Abort();
}
}
}
public class MediaCloser
{
public void CheckForStoppedPlayback()
{
while (true)
{
// continuously check for our stopped playback state to cleanup
Thread.Sleep(500);
if (SoundboardSingleton.Instance.WaveOutDevice != null &&
SoundboardSingleton.Instance.WaveOutDevice.PlaybackState == PlaybackState.Stopped)
{
SoundboardSingleton.Instance.CloseWaveOut();
SoundboardSingleton.Instance.IsBusy = false;
}
}
}
}
public class StayAliveBot
{
public void Live()
{
while (true)
{
// prevent bot from going idle
Thread.Sleep(1500000);
if (!SoundboardSingleton.Instance.IsBusy)
{
SoundboardSingleton.Instance.PlaySound(ConfigurationManager.AppSettings["SoundboardHeartbeatFile"]);
}
}
}
}
希望这可以帮助 运行 遇到同样问题的任何人。我的网站已经正常运行 运行 几个小时了,没有任何问题,而且客户向董事会发送垃圾邮件。再次感谢所有帮助过的人。
我的 Web 应用程序经常崩溃并重置 IIS 中的应用程序池,导致严重的性能问题,并且擦除我的应用程序中的所有计时线程 运行ning。
该站点是 .NET 4.5.2 C# MVC5 站点 运行 宁在 2012 Windows AWS 中的服务器 EC2 实例上。
这个问题是在我开始看到网站在 运行 几分钟后难以加载时第一次注意到的。我认为这可能是 ApplicationPool 回收,并确保在 IIS 中正确设置 IdleTime 和 Application Preload。问题仍然存在。
接下来我去服务器管理器检查事件日志,发现这些条目大约每 15 分钟发生一次:
Faulting application name: w3wp.exe, version: 8.5.9600.16384, time stamp: 0x5215df96 Faulting module name: WMNetMgr.dll_unloaded, version: 12.0.9600.17415, time stamp: 0x545047db Exception code: 0xc0000005 Fault offset: 0x00000000000cf5cf Faulting process id: 0x17d0 Faulting application start time: 0x01d331dc20f096d0 Faulting application path: c:\windows\system32\inetsrv\w3wp.exe Faulting module path: WMNetMgr.dll Report Id: 777a35de-9dd1-11e7-81d7-025ff0be916d Faulting package full name: Faulting package-relative application ID:
和
WIN-7PCRJOFR05F 5011 Warning Microsoft-Windows-WAS System 9/20/2017 7:01:04 AM - A process serving application pool 'SiteName' suffered a fatal communication error with the Windows Process Activation Service. The process id was '6096'. The data field contains the error number.
接下来我运行一个DebugDiag2的收集与分析:
WARNING - DebugDiag was not able to locate debug symbols for WMNetMgr.dll>, so the information below may be incomplete. In w3wp__SiteName__PID__5088__Date__09_20_2017__Time_06_31_02AM__436__Second_Chance_Exception_C0000005.dmp an access violation exception (0xC0000005) occured on thread 26 when another Module attempted to call the following unloaded Module: WMNetMgr.dll>.
Thread 26: Call Stack Unloaded_WMNetMgr.dll+cf5cf 0x000000de
575cf7c0 0x000000dc
2ed5ec10
这是此调试器报告的唯一错误。在报告的 .NET 堆栈跟踪中没有其他异常。我似乎无法获得此特定 .dll 的调试符号,而且消息似乎也不是很有帮助。
该应用程序利用 WMPLib 在 wmplayer 启动时创建一个单例实例,以通过来自客户端的 Web 请求在 Windows Server 2012 实例上播放声音。该应用程序在这方面可以正常播放声音和来自多个用户的请求。
这是单例:
public sealed class SoundboardSingleton : IDisposable
{
private static readonly Lazy<SoundboardSingleton> lazy =
new Lazy<SoundboardSingleton>(() => new SoundboardSingleton());
public static SoundboardSingleton Instance { get { return lazy.Value; } }
public WindowsMediaPlayer WMPlayer;
private StayAliveBot _liveBot;
private Thread _botThread;
private SoundboardSingleton()
{
WMPlayer = new WindowsMediaPlayer();
WMPlayer.settings.volume = 50;
_liveBot = new StayAliveBot();
_botThread = new Thread(_liveBot.Live);
_botThread.Start();
}
public void Dispose()
{
if (_botThread.IsAlive)
{
_botThread.Abort();
}
}
}
public class StayAliveBot
{
public void Live()
{
while (SoundboardSingleton.Instance != null)
{
Thread.Sleep(1500000);
SoundboardHelper.PlaySound("C:\SoundboardOpFiles\TestTone.wav");
}
}
}
并最初在 Startup.cs 中通过以下方式实例化:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
// startup soundboard singleton
SoundboardSingleton.Instance.WMPlayer.settings.volume = 50;
}
}
我可以在我的本地开发机器上 运行 这个应用程序,没有任何问题或崩溃。一切都按预期运行,没有崩溃。在部署到 EC2 实例时,网站上的一切正常,但现在每 15 分钟就会发生一次崩溃/重置。
我的怀疑是:
A) WMPLib 实例存在问题,缺少对 Windows Server 2012 框的依赖,允许它播放声音但会定期导致崩溃。
B) 我在单例实例化时犯了一个错误,它以某种方式使我的应用程序崩溃。
我已经尝试了 here 的解决方案,但没有结果。
如有任何帮助,我们将不胜感激。
编辑:我已经确认问题与 WMPLib 的使用有关,因为删除它的使用停止了每 15 分钟一次的崩溃。仍然不确定为什么会这样。
这不是对您问题的直接回答,而是对同一件事的不同处理方式。尝试使用 WPF 中的线程安全 MediaPlayer class 而不是 WMPLib COM 控件。添加对 WindowsBase 和 PresentationCore 的引用,并改用如下内容:
using System.Windows.Media;
public void PlaySound(string filename)
{
var mplayer = new MediaPlayer();
mplayer.MediaEnded += new EventHandler(MediaEndedHandler);
mplayer.Open(new Uri(filename));
mplayer.Play();
}
public void MediaEndedHandler(object sender, EventArgs e)
{
((MediaPlayer)sender).Close();
}
您也可以像上面一样将它用作单例,并且它是完全线程安全的,而 WMPLib 则不是。
编辑:
如评论中所述,您真的可以只使用带有 public 布尔值 属性 的静态 class 来显示忙音。 IIS 中的静态 class 在应用程序的所有请求之间共享,并且 class 仅在回收应用程序池时受到垃圾收集,因此您需要注意对象的生命周期您存储在其中,以避免内存消耗问题。此代码将为每个 PlaySound() 使用媒体播放器 class 的新实例,并在播放结束后立即处理它,但忙标志在对服务器发出的所有请求中很常见。
using System;
using System.Threading;
using System.Windows.Media;
namespace SoundBoardApp
{
public static class Soundboard
{
private static bool _isBusy = false;
public static bool IsBusy { get { return _isBusy; } }
private static void MediaEndedHandler(object sender, EventArgs e)
{
_isBusy = false;
var wmp = ((MediaPlayer)sender);
wmp.MediaEnded -= new EventHandler(MediaEndedHandler);
wmp.Close();
}
public static bool PlaySound(string filename)
{
if (!_isBusy)
{
_isBusy = true;
var wmp = new MediaPlayer();
wmp.MediaEnded += new EventHandler(MediaEndedHandler);
wmp.Volume = 0.5;
wmp.Open(new Uri(filename));
wmp.Play();
return true;
}
else
{
return false;
}
}
}
public class StayAliveBot
{
public void Live()
{
while (true)
{
Thread.Sleep(1500000);
if (!Soundboard.IsBusy) Soundboard.PlaySound("C:\SoundboardOpFiles\TestTone.wav");
}
}
}
}
我最终使用 NAudio 和我的单例模式。
根据 Lex Li 的建议,我使用了第三方,因为 Windows.MediaPlayer 不适用于网络应用程序。基于 Drunken Code Monkey 的解决方案,我在单例上使用了一个布尔标志来评估播放状态,该状态由一个单独的线程经常检查,该线程评估单例中 IWavePlayer 对象上的 PlaybackState.Stopped 值。我唯一关心的是性能。我还没有注意到任何问题,但我敢肯定,如果甚至可以从 Web 应用程序来管理事件,那么在处理程序中管理事件的性能会更高,代码也会更少。
代码如下:
using NAudio.Wave;
public sealed class SoundboardSingleton : IDisposable
{
private static readonly Lazy<SoundboardSingleton> lazy =
new Lazy<SoundboardSingleton>(() => new SoundboardSingleton());
public static SoundboardSingleton Instance { get { return lazy.Value; } }
public IWavePlayer WaveOutDevice { get; set; }
public AudioFileReader AudioFileReaderObj { get; set; }
public float Volume { get; set; }
private MediaCloser _mediaCloser;
private Thread _mediaCloserThread;
private StayAliveBot _liveBot;
private Thread _botThread;
public bool IsBusy { get; set; }
private SoundboardSingleton()
{
// checks our NAudio WaveOutDevice playback for stop
_mediaCloser = new MediaCloser();
_mediaCloserThread = new Thread(_mediaCloser.CheckForStoppedPlayback);
_mediaCloserThread.Start();
// thread to play sound every 25 minutes, to avoid idle flag
_liveBot = new StayAliveBot();
_botThread = new Thread(_liveBot.Live);
_botThread.Start();
}
public bool PlaySound(string filename)
{
// make sure we are not active
if (IsBusy) { return false; }
// process sound
IsBusy = true;
WaveOutDevice = new WaveOutEvent();
AudioFileReaderObj = new AudioFileReader(filename);
AudioFileReaderObj.Volume = Volume;
WaveOutDevice.Init(AudioFileReaderObj);
WaveOutDevice.Play();
return true;
}
public void CloseWaveOut()
{
// clean up sound objects
WaveOutDevice?.Stop();
if (AudioFileReaderObj != null)
{
AudioFileReaderObj.Dispose();
AudioFileReaderObj = null;
}
if (WaveOutDevice != null)
{
WaveOutDevice.Dispose();
WaveOutDevice = null;
}
}
public void Dispose()
{
if (_mediaCloserThread.IsAlive)
{
_mediaCloserThread.Abort();
}
if (_botThread.IsAlive)
{
_botThread.Abort();
}
}
}
public class MediaCloser
{
public void CheckForStoppedPlayback()
{
while (true)
{
// continuously check for our stopped playback state to cleanup
Thread.Sleep(500);
if (SoundboardSingleton.Instance.WaveOutDevice != null &&
SoundboardSingleton.Instance.WaveOutDevice.PlaybackState == PlaybackState.Stopped)
{
SoundboardSingleton.Instance.CloseWaveOut();
SoundboardSingleton.Instance.IsBusy = false;
}
}
}
}
public class StayAliveBot
{
public void Live()
{
while (true)
{
// prevent bot from going idle
Thread.Sleep(1500000);
if (!SoundboardSingleton.Instance.IsBusy)
{
SoundboardSingleton.Instance.PlaySound(ConfigurationManager.AppSettings["SoundboardHeartbeatFile"]);
}
}
}
}
希望这可以帮助 运行 遇到同样问题的任何人。我的网站已经正常运行 运行 几个小时了,没有任何问题,而且客户向董事会发送垃圾邮件。再次感谢所有帮助过的人。