如何在采取任何其他操作之前等待Autoreset事件发生?

时间:2011-11-08 23:53:01

标签: c# multithreading autoresetevent

这是关于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");


    }

此外,我移动了有关验证的数据传递到事件处理程序开头的部分,因此至少该部分被执行。这有帮助,但我不确定它是否正确。

2 个答案:

答案 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;
    //}
 }