基于C#的Windows服务-尝试在生产环境中进行JIT调试
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了基于C#的Windows服务-尝试在生产环境中进行JIT调试,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含18344字,纯文字阅读大概需要27分钟。
内容图文
![基于C#的Windows服务-尝试在生产环境中进行JIT调试](/upload/InfoBanner/zyjiaocheng/949/304e6e21e7d84e7e8d538d1f9df2431d.jpg)
我在投入生产的服务的事件日志中收到此错误:
An unhandled win32 exception occurred
in RivWorks.FeedHandler.exe [5496].
Just-In-Time debugging this exception
failed with the following error:
Debugger could not be started because
no user is logged on.
我已经在Win NT全局帐户下安装并运行它.我不知道为什么它要尝试进入调试模式.它是在“发布”模型下构建的.在4.0 Framework上运行.
当我在开发机上通过EXE入口点而不是WinSvc入口点运行时,一切运行正常-但是-我已经处于“调试”模式.
关于寻找什么的任何想法?
2010-10-21-注意-更改了代码库.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using sysIO = System.IO;
using RivWorks.FeedHandler;
using System.Collections;
namespace RivWorks.FeedHandler.Service
{
public partial class FeedListener : ServiceBase
{
#region Declarations
private List<string> _keys = new List<string>();
private System.Threading.Timer _clock = null;
private FileSystemWatcher _watcher;
private BackgroundWorker _worker;
private Queue<string> _queue = new Queue<string>();
private bool _isDequeueing = false;
#endregion
#region Constructor
public FeedListener()
{
InitializeComponent();
}
#endregion
#region Start/Stop
protected override void OnStart(string[] args)
{
try
{
WriteToEventLog("Enter Start", EventLogEntryType.Information);
_keys.AddRange(new string[] { "csv", "xml", "zip", "rivx" });
_worker = new BackgroundWorker();
_worker.WorkerReportsProgress = true;
_worker.WorkerSupportsCancellation = true;
_worker.DoWork += new DoWorkEventHandler(BackgroundWorkerDoWork);
_worker.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorkerProgressChanged);
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerRunWorkerCompleted);
_watcher = new FileSystemWatcher(AppSettings.Default.FTPRootPath, "*.*");
_watcher.IncludeSubdirectories = true;
_watcher.NotifyFilter = sysIO.NotifyFilters.DirectoryName | sysIO.NotifyFilters.FileName | sysIO.NotifyFilters.LastAccess | sysIO.NotifyFilters.CreationTime | sysIO.NotifyFilters.LastWrite;
_watcher.Created += new sysIO.FileSystemEventHandler(fileCreatedOrChanged);
_watcher.Changed += new sysIO.FileSystemEventHandler(fileCreatedOrChanged);
_watcher.EnableRaisingEvents = true;
// check every 15 minutes...
_clock = new System.Threading.Timer(Tick, null, 0, 900000);
WriteToEventLog("Exit Start", EventLogEntryType.Information);
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
this.Stop();
}
}
protected override void OnStop()
{
try
{
_watcher.Dispose();
_watcher = null;
_clock.Dispose();
_clock = null;
_worker.Dispose();
_worker = null;
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
#endregion
#region Event Handlers
void fileCreatedOrChanged(object sender, sysIO.FileSystemEventArgs e)
{
try
{
WriteToEventLog("Enter fileCreatedOrChanged", EventLogEntryType.Information);
if (!_queue.Contains(e.FullPath))
_queue.Enqueue(e.FullPath);
if (!_isDequeueing)
DeQueue();
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
#endregion
#region Do work on another Thread
void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
try
{
WriteToEventLog("Enter BackgroundWorkerDoWork", EventLogEntryType.Information);
BackgroundWorker bw = sender as BackgroundWorker;
WriteToEventLog("Create Handler", EventLogEntryType.Information);
RivWorks.FeedHandler.Library.Handler handler = new RivWorks.FeedHandler.Library.Handler(Convert.ToBoolean(AppSettings.Default.InProduction), AppSettings.Default.ArchivePath);
WriteToEventLog("Setup Handler", EventLogEntryType.Information);
handler.Keys = _keys;
handler.RootDirectory = AppSettings.Default.RootDirectory;
handler.FtpPath = AppSettings.Default.FTPRootPath;
handler.WorkPath = AppSettings.Default.WorkPath;
handler.ArchivePath = AppSettings.Default.ArchivePath;
handler.EmailHost = AppSettings.Default.EmailHost;
handler.EmailPassword = AppSettings.Default.EmailPassword;
handler.EmailUser = AppSettings.Default.EmailUser;
handler.ErrorNotificationRecipients = AppSettings.Default.ErrorNotificationRecipients;
handler.InProduction = Convert.ToBoolean(AppSettings.Default.InProduction);
Library.DTO.FileHandler fileHandler = new Library.DTO.FileHandler(handler.FtpPath, handler.WorkPath, handler.ArchivePath, (string)e.Argument);
WriteToEventLog("Call Handler.Execute", EventLogEntryType.Information);
handler.Execute(bw, e, fileHandler);
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
finally
{
WriteToEventLog("Exit BackgroundWorkerDoWork", EventLogEntryType.Information);
}
}
void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
if (e.ProgressPercentage >= 100)
{
}
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
try
{
if (e.Cancelled)
{
WriteToEventLog("Cancelled.", EventLogEntryType.Warning);
if (e.Error != null)
{
WriteToEventLog(e.Error, EventLogEntryType.Error);
}
}
else if (e.Error != null)
{
WriteToEventLog(e.Error, EventLogEntryType.Error);
}
else
{
WriteToEventLog("Successfully completed.", EventLogEntryType.Information);
}
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
#endregion
#region Private Methods
private void Tick(object data)
{
try
{
if (!_isDequeueing)
{
WriteToEventLog("Enter Tick. FTP Root = " + AppSettings.Default.FTPRootPath, EventLogEntryType.Information);
foreach (string key in _keys)
{
List<string> files = Directory.GetFiles(Path.Combine(AppSettings.Default.FTPRootPath), "*." + key, SearchOption.AllDirectories).ToList();
foreach (string fileName in files)
{
if (File.Exists(fileName))
{
// Toss this file name into the Queue...
WriteToEventLog("Call _queue.Enqueue(" + fileName + ")", EventLogEntryType.Information);
if (!_queue.Contains(fileName))
_queue.Enqueue(fileName);
}
}
}
// Now, start handling the list of files...
DeQueue();
}
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
finally
{
WriteToEventLog("Exit Tick", EventLogEntryType.Information);
}
}
private void DeQueue()
{
try
{
_isDequeueing = true;
WriteToEventLog("Enter DeQueue", EventLogEntryType.Information);
while (_queue.Count > 0)
{
string queuedFile = _queue.Dequeue();
WriteToEventLog("DeQueued " + queuedFile, EventLogEntryType.Information);
bool isValid = false;
foreach (string key in _keys)
{
if (Path.GetExtension(queuedFile).Replace(".", "").Equals(key, StringComparison.CurrentCultureIgnoreCase))
isValid = true;
}
if (isValid)
{
// Now, spin up a new thread and do the work on the file, based on file type...
WriteToEventLog("Call RunWorkerAsync", EventLogEntryType.Information);
string UserName = Path.GetDirectoryName(queuedFile).Replace(AppSettings.Default.FTPRootPath, "").Replace("\\", "");
int i = 0;
DateTime sTime = DateTime.Now;
DateTime eTime = DateTime.Now;
_worker.RunWorkerAsync(queuedFile); // goes to BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) //
while(_worker.IsBusy)
{
System.Threading.Thread.Sleep(5000);
i++;
}
eTime = DateTime.Now;
TimeSpan ts = new TimeSpan(eTime.Ticks - sTime.Ticks);
string msg = String.Format("Import for {0} started at {1} and ended at {2}. It took {3} cycles and the elapsed time was {4}:{5}:{6}.", UserName, sTime, eTime, i, ts.Hours, ts.Minutes, ts.Seconds);
WriteToEventLog(msg, EventLogEntryType.Information);
}
}
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
finally
{
_isDequeueing = false;
WriteToEventLog("Exit DeQueue", EventLogEntryType.Information);
}
}
private void WriteToEventLog(Exception ex, EventLogEntryType eventLogEntryType)
{
try
{
string message = string.Empty;
string sTrace = ex.StackTrace;
while (ex != null)
{
message = message + Environment.NewLine + Environment.NewLine + ex.Message;
ex = ex.InnerException;
}
message = message + Environment.NewLine + Environment.NewLine + sTrace;
WriteToEventLog(message, eventLogEntryType);
}
catch (Exception ex2)
{
WriteToEventLog(ex2.Message, EventLogEntryType.Error);
}
}
private void WriteToEventLog(string message, EventLogEntryType eventLogEntryType)
{
try
{
this.EventLog.WriteEntry(message, eventLogEntryType);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
}
}
2010-10-20-注意-添加了服务代码文件.也许这里有一个基本的错误?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using sysIO = System.IO;
using RivWorks.FeedHandler;
namespace RivWorks.FeedHandler.Service
{
public partial class FeedListener : ServiceBase
{
#region Declarations
private List<string> _keys = new List<string>();
private System.Threading.Timer _clock = null;
private FileSystemWatcher _watcher;
private BackgroundWorker _worker;
static private bool _isBusy = false;
#endregion
#region Constructor
public FeedListener()
{
InitializeComponent();
}
#endregion
#region Start/Stop
protected override void OnStart(string[] args)
{
try
{
_keys.AddRange(new string[] { "csv", "xml", "zip", "rivx" });
_worker = new BackgroundWorker();
_worker.WorkerReportsProgress = true;
_worker.WorkerSupportsCancellation = true;
_worker.DoWork += new DoWorkEventHandler(BackgroundWorkerDoWork);
_worker.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorkerProgressChanged);
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerRunWorkerCompleted);
_watcher = new FileSystemWatcher(AppSettings.Default.FTPRootPath, "*.*");
_watcher.IncludeSubdirectories = true;
_watcher.NotifyFilter = sysIO.NotifyFilters.DirectoryName | sysIO.NotifyFilters.FileName | sysIO.NotifyFilters.LastAccess | sysIO.NotifyFilters.CreationTime | sysIO.NotifyFilters.LastWrite;
_watcher.Created += new sysIO.FileSystemEventHandler(fileCreatedOrChanged);
_watcher.Changed += new sysIO.FileSystemEventHandler(fileCreatedOrChanged);
_watcher.EnableRaisingEvents = true;
// check every 5 minutes...
_clock = new System.Threading.Timer(Tick, null, 0, 300000);
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
this.Stop();
}
}
protected override void OnStop()
{
try
{
_watcher.Dispose();
_watcher = null;
_clock.Dispose();
_clock = null;
_worker.Dispose();
_worker = null;
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
#endregion
#region Event Handlers
void fileCreatedOrChanged(object sender, sysIO.FileSystemEventArgs e)
{
try
{
DTO.BackgroundWorkerEventArgs eventArgs = new DTO.BackgroundWorkerEventArgs();
sysIO.WatcherChangeTypes myType = e.ChangeType;
bool isValid = false;
foreach (string key in _keys)
{
if (Path.GetExtension(e.FullPath).Replace(".", "").Equals(key, StringComparison.CurrentCultureIgnoreCase))
isValid = true;
}
if (isValid)
{
eventArgs.PathAndFile = e.FullPath;
eventArgs.Key = Path.GetExtension(e.FullPath).ToLower().Replace(".", "");
eventArgs.FileName = Path.GetFileName(e.FullPath);
eventArgs.Path = Path.GetDirectoryName(e.FullPath);
eventArgs.UserName = Path.GetDirectoryName(e.FullPath).Replace(AppSettings.Default.FTPRootPath, "").Replace("\\", "");
eventArgs.IsRunning = true;
System.Threading.Thread.Sleep(30000);
// Now, spin up a new thread and do the work on the file, based on file type...
_isBusy = true;
_worker.RunWorkerAsync(eventArgs); // goes to BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) //
int i = 0;
DateTime sTime = DateTime.Now;
DateTime eTime = DateTime.Now;
while (_isBusy)
{
System.Threading.Thread.Sleep(5000);
i++;
}
eTime = DateTime.Now;
TimeSpan ts = new TimeSpan(eTime.Ticks - sTime.Ticks);
string msg = String.Format("Import for {0} started at {1} and ended at {2}. It took {3} cycles and the elapsed time was {4}:{5}:{6}.", eventArgs.UserName, sTime, eTime, i, ts.Hours, ts.Minutes, ts.Seconds);
WriteToEventLog(msg, EventLogEntryType.Information);
}
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
#endregion
#region Do work on another Thread
void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
try
{
RivWorks.FeedHandler.Handler handler = new RivWorks.FeedHandler.Handler();
BackgroundWorker bw = sender as BackgroundWorker;
handler.Execute(bw, e);
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
finally
{
_isBusy = false;
}
}
void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
if (e.ProgressPercentage >= 100)
{
_isBusy = false;
}
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
try
{
if (e.Cancelled)
{
WriteToEventLog("Cancelled.", EventLogEntryType.Warning);
if (e.Error != null)
{
WriteToEventLog(e.Error, EventLogEntryType.Error);
}
}
else if (e.Error != null)
{
WriteToEventLog(e.Error, EventLogEntryType.Error);
}
else
{
WriteToEventLog("Successfully completed.", EventLogEntryType.Information);
}
_isBusy = false;
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
#endregion
#region Private Methods
private void Tick(object data)
{
try
{
foreach (string key in _keys)
{
List<string> files = Directory.GetFiles(Path.Combine(AppSettings.Default.FTPRootPath), "*." + key, SearchOption.AllDirectories).ToList();
foreach (string fileName in files)
{
System.Threading.Thread.Sleep(5000);
if (File.Exists(fileName))
{
DateTime lat = File.GetLastWriteTime(fileName);
try
{
File.SetLastWriteTime(fileName, DateTime.Now);
}
catch
{
// just catch and ignore with a short pause...
System.Threading.Thread.Sleep(5000);
}
}
}
}
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
private void WriteToEventLog(Exception ex, EventLogEntryType eventLogEntryType)
{
try
{
string message = string.Empty;
string sTrace = ex.StackTrace;
while (ex != null)
{
message = message + Environment.NewLine + Environment.NewLine + ex.Message;
ex = ex.InnerException;
}
message = message + Environment.NewLine + Environment.NewLine + sTrace;
this.EventLog.WriteEntry(message, eventLogEntryType);
}
catch (Exception ex2)
{
WriteToEventLog(ex2, EventLogEntryType.Error);
}
}
private void WriteToEventLog(string message, EventLogEntryType eventLogEntryType)
{
try
{
this.EventLog.WriteEntry(message, eventLogEntryType);
}
catch (Exception ex)
{
WriteToEventLog(ex, EventLogEntryType.Error);
}
}
#endregion
}
}
解决方法:
即使它作为发行版exe运行,您仍然可以选择在应用程序崩溃时附加到调试器…您将不会看到调试符号,而只能看到汇编:)
我相信是Dr. Watson流程捕获了应用程序错误以进行调试…因为您的应用程序是服务,所以Watson Dr.无法与桌面进行交互,从而给您看到的错误.您可以转到服务属性,并在“登录”选项卡上标记“允许服务与桌面进行交互”,当应用程序崩溃时,该选项将为您提供Dr. Watson弹出窗口.
禁用Watson博士的步骤如下:
http://support.microsoft.com/kb/188296
如果要在服务器上调试应用程序,则可以在服务器上启用远程调试,并将Visual Studio附加到进程中.如果要尝试这样做,我可以为您提供更多远程调试Windows服务的提示.
HTH,
詹姆士
*编辑*
根据您提供的代码,我将研究以下领域:
> AppSettings.Default.FTPRootPath是否在App.Config中正确设置?
>服务启动后,该目录是否立即发生更改?您将计时器注释为“每五分钟检查一次”,这有点令人困惑,因为一旦将EnableRaisingEvents设置为true,FileSystemWatcher就会开始接收事件.因此问题实际上可能在fileCreatedOrChanged中
>按照这些思路,您有一个BackgroundWorker服务多个事件,更糟糕的是,您是异步触发处理程序的.这是我最可能的怀疑,因为如果在第一个作业运行时再次调用_worker.RunWorkerAsync(),则会收到InvalidOperationException.虽然我不确定为什么您不会在日志中看到
>您正在使用计时器更新监视目录中所有文件的上次写入时间,并且每五秒钟执行一次.这似乎是一个非常糟糕的主意…我不确定您要完成什么.这将触发FileSystemWatcher的changed事件,这将说明您为什么在启动后不到10秒崩溃(计时器的初始滴答被设置为立即触发,这意味着五秒钟后您更改所有文件时间,从而触发FileSystemWatcher之后不久多次)
因此,我最好的猜测是,在五秒钟之内,您已经开始在同一个BackgroundWorker上触发多个RunWorkAsync()调用,这是不可以的:)
将静态变量_isBusy设置为true / false是不可靠的,因为您正在与BackgroundWorkers进行多线程…您需要使用Mutex或其他一些锁,但这并没有真正违反使用BackgroundWorker的目的. ?
另外,如果您想使用isBusy标志之类的东西,它必须看起来更像:
while (_isBusy) {
System.Threading.Thread.Sleep(5000);
}
_isBusy = true;
_worker.RunWorkerAsync(eventArgs);
在尝试启动Background worker之前,您需要_isBusy为假…按照您的方式使用它,如果事件触发100次,则您将进行100次调用.
解决问题的最简单方法是,在每次事件触发时,在fileCreatedOrChanged方法中创建一个新的BackgroundWorker …创建这么多新线程会涉及开销,但是如果用此方法完成的工作量很大,那将是值得开销.
您可能可以依赖于内置的BackgroundWorker.IsBusy属性,但是同样,如果您只是阻塞直到后台工作程序完成,我就不得不质疑异步线程的好处.
**编辑**
现在,我了解了您要通过初始文件时间戳更改来完成的工作…我认为最好不要留下时间戳,而只需通过启动循环来处理现有文件即可.您可以为每个线程生成一个后台工作线程,就像在FileSystemWatcher命名上一样.处理它的方式是故意创建副作用以触发所需的结果.
我在不断增加的复杂性上失去了一点跟踪…整个队列/出队的事情可能是不必要的.也许我只是没有看到真正存在的需求.同样,令我震惊的是,您正在异步启动后台工作程序,然后将主线程置于睡眠状态,直到完成.
当您使主线程进入睡眠状态时,不会处理任何事件,因此您实际上是将多线程限制为一个线程.我看到您想向事件日志写入一个线程需要多长时间.我将开始第二个答案,以解决是否有机会,但要点是将Stopwatch类(它将为您提供在操作过程中传递的毫秒数或CPU滴答数的准确计数)到DoWorkEventArgs .Result属性.
但是您要求的代码!基本上,无论您决定调用_worker.RunWorkerAsync(queuedFile),而不是每次运行一个类级别的BackgroundWorker,都每次都创建一个新的.为事件处理程序等传递所有相同的参数.您的服务入口点将删除所有BGW引用,如下所示:
protected override void OnStart(string[] args)
{
try
{
_keys.AddRange(new string[] { "csv", "xml", "zip", "rivx" });
_watcher = new FileSystemWatcher(AppSettings.Default.FTPRootPath, "*.*");
_watcher.IncludeSubdirectories = true;
_watcher.NotifyFilter = sysIO.NotifyFilters.DirectoryName | sysIO.NotifyFilters.FileName | sysIO.NotifyFilters.LastAccess | sysIO.NotifyFilters.CreationTime | sysIO.NotifyFilters.LastWrite;
_watcher.Created += new sysIO.FileSystemEventHandler(fileCreatedOrChanged);
_watcher.Changed += new sysIO.FileSystemEventHandler(fileCreatedOrChanged);
_watcher.EnableRaisingEvents = true;
WriteToEventLog("Exit Start", EventLogEntryType.Information);
}
并且异步运行BGW的代码将变为:
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += new DoWorkEventHandler(BackgroundWorkerDoWork);
worker.ProgressChanged += BackgroundWorkerProgressChanged; // Note you don't need
worker.RunWorkerCompleted += BackgroundWorkerRunWorkerCompleted; // the 'new' here
worker.RunWorkerAsync(queuedFile); // goes to BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) //
内容总结
以上是互联网集市为您收集整理的基于C#的Windows服务-尝试在生产环境中进行JIT调试全部内容,希望文章能够帮你解决基于C#的Windows服务-尝试在生产环境中进行JIT调试所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。