这是关于C#中的AutoResetEvent
。我试着阅读其他答案,但我无法理解并适用于我的场景。我不是在编写任何线程应用程序。只是一个小应用程序来读取/验证文件和更新。
所以我有这个要求写一些代码来读取一个固定长度的文件,验证它然后如果有效则将它上传到数据库。
在我遇到AutoResetEvent
之前,我一切正常。所以这是正在发生的事情。解析/读取数据后,我使用C#中的Flat File Checker实用程序对其进行验证。所以我将函数调用到我的应用程序中。这是片段。
private AutoResetEvent do_checks = new AutoResetEvent(false);
public bool ValidationComplete = false;
这部分介绍初始化代码:
this._files.Validated += new EventHandler<SchemaValidatedEventArgs>(FileSetValidated);
public bool ValidateFile()
{
try
{
RunValidation();
return true;
}
catch (Exception e)
{
log.Error("Data Validation failed because :" + e.Message);
return false;
}
}
private void RunValidation()
{
// Use Flat File Checker user interface to create Schema file.
do_checks = _files.RunChecks();
log.Debug("Validation Started");
}
这是在验证过程中被称为asnchronusly的方法:
public void FileSetValidated(Object sender, SchemaValidatedEventArgs e)
{
try
{
ValidationComplete = e.Result;
if (IsDataValid)
{
log.Debug("Data is validated and found to be valid.");
}
else
{
log.Debug("Data is validated and found to be Invalid");
}
}
finally
{
do_checks.Set();
}
}
发生的事情是,即使在我将任何值设置为ValidationComplete
之前,代码也会检查验证是否完成,并且因为它默认设置为false,所以它返回false。 FileSetValidated
之后的代码在此之后执行,因此数据库更新永远不会发生。
原因是我无法更改代码,因为Flat File Checker在RunChecks方法中只接受AutoResetEvent
作为返回变量。
** * *** 以下是我现在所做的的 * ** * ** * private AutoResetEvent do_checks;
public bool ValidateFile()
{
try
{
string extFilePath = surveyFile.ExtFilePath;
File.Copy(extFilePath, localTempFolder + "ExtractFile.Dat");
RunValidation();
if (!do_checks.WaitOne(TimeSpan.FromSeconds(30))) {
// throw new ApplicationException("Validation took more than expected!");
}
return true;
}
catch (Exception e)
{
log.Error("Data Validation failed because :" + e.Message);
return false;
}
}
private void RunValidation()
{
// Use Flat File Checker user interface to create Schema file.
do_checks = _files.RunChecks();
do_checks.WaitOne();
log.Debug("Validation Started");
}
此外,我移动了有关验证的数据传递到事件处理程序开头的部分,因此至少该部分被执行。这有帮助,但我不确定它是否正确。
答案 0 :(得分:1)
我从未使用过lib,所以我只是下载了它并查看了代码。
首先,由于已经提到“500 - 内部服务器错误”,似乎缺少部分代码,至少在FileSetValidated方法中“尝试”。我没有看到您通过 WaitOne 等待活动的地方。
您不需要自己创建 do_checks ,因为 _files.RunChecks()会为此特定文件的处理创建AutoResetEven。因此,如果您对该事件使用相同的字段 - 如果您需要同时处理少量文件,则会出现问题。因此,为每个文件保留单独的事件,在任何情况下,如果您不想在中间停止处理,我认为没有理由将该引用保留为成员(如果您将调用 do_checks.Set()在处理过程中,它将取消处理而不完成处理。)
正如我在lib代码看,则不应在 FileSetValidated 方式调用的 do_checks.Set()下,因为它将被设置,一旦处理将完成,所以你可以写:
var do_checks = _files.RunChecks();
do_checks.WaitOne();
如果有帮助,请随意分享。
<强>更新强> 我现在无法检查lib是否解决了为什么在开始处理后设置了 do_checks ,但我建议您在下一步 RunValidation 方法中使用初始代码:
private void RunValidation()
{
do_checks.Reset(); //reset state
_files.RunChecks(); //don't store event from the lib
log.Debug("Validation Started");
do_checks.WaitOne(); //Wait for FileSetValidated to set this event
}
答案 1 :(得分:0)
在退出ValidateFile函数之前,您需要等待验证完成(等待AutoResetEvent)并返回验证结果。
尝试这样的事情:
public bool ValidateFile()
{
//try
{
RunValidation();
//Allocate enough time for the validation to occur but make sure
// the application doesn't block if the _files.Validated event doesn't get fired
if(!do_checks.WaitOne(TimeSpan.FromSeconds(10)))
{
throw ApplicationException("Validation took more than expected!");
}
return ValidationComplete;
}
//I would not catch the exception since having an error doesn't mean that the file
//is invalid. Catch it upper in the call stack and inform the user that the validation
//could not be performed because of the error
//catch (Exception e)
//{
// log.Error("Data Validation failed because :" + e.Message);
// return false;
//}
}