2011-11-08 29 views
1

這是關於C#中的AutoResetEvent。我試圖閱讀其他答案,但我無法理解並適用於我的場景。我不寫任何線程應用程序。只是一個小的應用程序來讀取/驗證文件和更新。 所以我有這個需求來編寫一些代碼來讀取一個固定長度的文件,驗證它,然後如果它是有效的上傳到數據庫。如何在採取任何其他操作之前等待Autoreset事件發生?

我得到了一切工作,直到我被困在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"); 
} 

這是得到驗證過程中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中的代碼被執行,所以數據庫更新從不發生。

原因是我無法更改代碼,因爲平面文件檢查器只接受AutoResetEvent作爲RunChecks方法中的返回變量。

** * ***這是我現在* ** * ** * 私人的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"); 


    } 

而且我搬到哪裏有關驗證數據被傳遞對事件處理程序的開頭,以便ATLEAST一部分被執行的部分。這有幫助,但我不確定它是否正確。

+0

這裏有一些作品缺失。您正在創建do_checks事件,但稍後會分配RunChecks()返回的內容,從而覆蓋您之前創建的內容。你上面說過,RunValidation只接受一個AutoResetEvent,但RunValidation是你的,不接受任何東西。 RunChecks返回一個。您可能需要等待RunChecks返回的內容。 –

+0

謝謝!!! RunChecks正在返回AutoReset事件是正確的。所以我在不同的地方使用這個AutoReset事件。我如何在不同的功能中引用它?所以我只是定義它,沒有分配,後來當RunChecks返回我分配它。你認爲那是正確的嗎? – MadCoder

回答

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(); 

如果有幫助,請隨時分享。

UPDATE: 我不能檢查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 
} 
+0

感謝您的回覆。我試圖在各個地方添加WaitOne,但它似乎並沒有工作,所以我擺脫了它。所以當我將上面的代碼添加到我的代碼中時,驗證會隨機發生。有時我得到我想要的東西,有時候我沒有。所以這就是我所做的:聲明Autoreset事件,與runchecks一起使用並添加waitone。並在runvalidation()中添加了上一章中給出的答案。所以它確實執行了我知道Data是否有效的部分,然後像異步更新數據庫一樣。希望我做得正確。謝謝 – MadCoder

+0

你應該只留下一個WaitOne--在** ValidateFile **或** RunValidation **中。這就是爲什麼你會在'if(!do_checks.WaitOne(TimeSpan.FromSeconds(30)){' –

+0

}中隨時獲得Exception。如果我擺脫其中一個,程序不會等待驗證發生。讓我今天進行一些測試,看看。再次感謝。我也想把這兩個作爲答案。我不知道該怎麼做。 – MadCoder

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; 
    //} 
} 
+0

感謝您的回答。現在我嘗試了這個例子,所以無論我做什麼,我總是得到這個ApplicationException,我試過10秒20秒30秒。但我所做的是我將這個答案和下面的一個答案結合起來並寫下來。我會發布它。但是這段代碼會讓代碼等待驗證發生。 – MadCoder

相關問題