我有以下简单的代码块
var assmSpec = util.ASSEMBLYFOLDER + task.AssemblyName; // evals to valid fileSpec
if (!File.Exists(assmSpec))
throw new TaskException(string.Format(
"Assembly [{0}] cannot be located.", assmSpec));
由于assmSpec引用的程序集实际上确实存在(File.Exists()
的值为true),因此我预计异常将而不是被抛出。但事实的确如此。代码步进throw语句。为了调试,我将代码修改为:
var assmSpec = util.ASSEMBLYFOLDER + task.AssemblyName; // evals to valid fileSpec
var asmExists = File.Exists(assmSpec);
if (!asmExists)
throw new TaskException(string.Format(
"Assembly [{0}] cannot be located.", assmSpec));
这里,asmExists
的值为true,代码仍然进入throw。
然后将代码修改为:
var assmSpec = util.ASSEMBLYFOLDER + task.AssemblyName; // evals to valid fileSpec
if (!File.Exists(assmSpec) && File.Exists(assmSpec))
throw new TaskException(string.Format(
"Assembly [{0}] cannot be located.", assmSpec));
,代码仍然会抛出。这里显然出了很大的问题。有人能解释一下吗?我做了什么明显很蠢的事吗?
现在,这段代码是在一个方法中,它也有一个try - catch - finally结构,但它在所有这些之前(在try之前)…
完整的方法是:
public void StartProcess(Task task)
{
log.Write(log.Level.Debug, string.Format(
"TaskWorker.StartProcess {0} process",
task.Name), task.Name);
WorkerMessageManager.MsgArrvdWorkerHndlr += MsgArrvdWorkerHndlr;
var tskName = task.Name;
var assmSpec = util.ASSEMBLYFOLDER + task.AssemblyName;
if (!File.Exists(assmSpec))
throw new TaskException(string.Format(
"Assembly [{0}] cannot be located.", assmSpec));
try
{
WorkerMessageManager.NotifyWorker(new ProgressTaskMessage(
tskName, "", tskName + " starting..."));
// -------------------------------------------
Assembly dA;
try { dA = Assembly.LoadFrom(assmSpec); }
catch(FileNotFoundException nfX)
{ throw new TaskException(string.Format(
"Assembly [{0}] cannot be located.", assmSpec),
nfX); }
// -------------------------------------------
var iTsk = (IExecuteTasks)dA.CreateInstance(task.ClassName);
if (iTsk == null)
throw new TaskException(
string.Format("Unable to instantiate {0} from {1}",
task.ClassName, task.AssemblyName));
if (iTsk.TaskName != tskName) // do not execute if names do not match
throw new TaskNameMismatchException(string.Format(
"CHECK CONFIGURATION SETTINGS, Data Task Name Mismatch.{0}" +
"Task name defined in TaskScheduler.config [{1}], {0} does " +
"not match name [{2}] as defined in Task Logic assembly: {3}.{4}",
sNL, tskName, iTsk.TaskName, task.AssemblyName,
task.ClassName), tskName, iTsk.TaskName);
// -------------------------------------------
iTsk.DataImportProgressEvent += OnProgressReport;
iTsk.ProcessCompletedEvent += OnProcessCompleted;
iTsk.GeneralEvent += OnGeneralEvent;
// -----------------------------------
log.Write(log.Level.Debug, string.Format(
"{0} process Started", task.Name),
task.Name);
if (task.JobQueue.HasJobReady)
iTsk.StartTask(JobQueues.Instance.DeQueue(tskName));
else iTsk.StartTask();
log.Write(log.Level.Debug, string.Format(
"{0} process Completed", task.Name),
task.Name);
}
catch (TaskNameMismatchException inmX)
{ log.Write(log.Level.Warn, inmX.Message, tskName, inmX); }
catch (BpaTaskException mX)
{
var errMsg = string.Format(
"Error in Data Import StartProcess(). " + sNL +
"Exception {0}: {1}, " + sNL +
"Stack Trace: {2}",
mX, mX.Message, mX.StackTrace);
log.Write(log.Level.Error, errMsg,
task.Name, mX);
}
catch(Exception X)
{
var errMsg = string.Format(
"Error in Data Import StartProcess(). " + sNL +
"Exception {0}: {1}, " + sNL +
"Stack Trace: {2}",
X, X.Message, X.StackTrace);
log.Write(log.Level.Error, errMsg, task.Name, X);
// WorkerMessageManager.NotifyWorker(new ImportFailMessage(X));
// This throw instruction causes the Scheduler service to stop alltogether
// I'm Removing the throw for now, because it seems inappropriate to
// kill the whole service..
throw;
}
finally
{
task.IsRunning = false;
WorkerMessageManager.MsgArrvdWorkerHndlr -= MsgArrvdWorkerHndlr;
}
}
检查同一行if ()
语句后是否有文本(代码或分号)。最有可能的原因是"throw"实际上并不在if语句内,所以它总是被执行。
检查你正在调试一个DEBUG版本——你可能会在RELEASE版本的调试器中得到奇怪的报告值,这可能会使它看起来好像一个变量是真的,而实际上它是假的。
在某些情况下(尽管通常只有在引用预编译的dll或损坏的pdb文件时),查看与调试不同的代码也是可能的,这给人的印象是您对源代码所做的更改被忽略了。执行Build> Clean,检查您正在运行的程序集不再存在于磁盘上,然后重新构建它以确保它是最新的并与您的源代码同步。
我刚刚尝试了类似的东西,它对我来说很好。您是否尝试过使用语句块而不是单个抛出行?
编译器可能会混淆,并且可能需要重新启动。这并非闻所未闻。:/
如果您查看文件的内部。方法,您会发现在许多情况下它将返回false,包括:
- 路径为空或空字符串
- 文件不存在
- 操作系统认为该文件实际上是一个目录
- 试图访问文件的帐户没有读权限。
- 抛出其他内部NotSupportedException、SecurityException、IOException或UnauthorizedAccessException。
问题是所有这些潜在的错误都被隐藏了。我建议尝试FileInfo
类代替:
var fileInfo = new FileInfo( assmSpec );
if ( !fileInfo.Exists )
throw new TaskException( ...
FileInfo的构造函数会抛出一个异常给你,这可能会给你更多关于这个问题的信息。