Как ждать события автоматического сброса, прежде чем предпринимать какие-либо другие действия? - PullRequest
1 голос
/ 09 ноября 2011

Это примерно AutoResetEvent в C #.Я пытался читать другие ответы, но не мог понять смысл и применить к своему сценарию.Я не пишу какие-либо потоки приложений.Просто небольшое приложение для чтения / проверки файла и обновления.Поэтому у меня есть требование написать код для чтения файла фиксированной длины, его проверки, а затем, если он действителен, загрузить его в базу данных.

У меня все работало, пока я не застрял с AutoResetEvent.Итак, вот что происходит.После того, как данные проанализированы / прочитаны, я проверяю их, используя утилиту проверки плоских файлов в C #.Поэтому я вызвал функции в свое приложение.Вот фрагмент кода.

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");
}

Этот метод вызывается асинхронно во время процесса проверки:

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, код проверяется на Завершение проверки, и потому что это установлено по умолчанию в ложь, это возвращает ложь.Код в FileSetValidated выполняется после этого, поэтому обновление базы данных никогда не происходит.

Причина в том, что я не могу изменить код, потому что средство проверки плоских файлов принимает только AutoResetEvent в качестве возвращаемой переменной в RunChecksметод.

****** Вот что я сделал сейчас ******* 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 ]

1 голос
/ 09 ноября 2011

Я никогда не работал с этой библиотекой, поэтому я просто скачал ее и изучил код.

Прежде всего, как уже упоминалось "500 - Internal Server Error", кажется, что часть кода отсутствует, по крайней мере, "try" в методе FileSetValidated. Я не вижу места, где вы ожидаете события через WaitOne .

Вам не нужно создавать do_checks самостоятельно, потому что _files.RunChecks () создает AutoResetEven для обработки этого конкретного файла. Поэтому, если вы используете одно и то же поле для этого события - у вас возникнет проблема, если вам потребуется обрабатывать несколько файлов одновременно. Поэтому сохраняйте отдельное событие для каждого файла, в любом случае я не вижу смысла сохранять эти ссылки в качестве членов, если вы не хотите останавливать обработку в середине (если вы будете вызывать do_checks.Set () во время обработки отменит обработку, не завершив ее).

Как я вижу в коде lib, вы не должны вызывать do_checks.Set () в методе FileSetValidated , потому что он будет установлен, как только будет выполнена обработка, поэтому Вы можете просто написать:

var do_checks = _files.RunChecks();
do_checks.WaitOne(); 

Не стесняйтесь поделиться, если это помогло.

UPDATE: Сейчас я не могу проверить эту библиотеку, чтобы понять, почему 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
}
0 голосов
/ 09 ноября 2011

Перед выходом из функции 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;
    //}
 }
...