簡體   English   中英

通過任務報告/記錄

[英]Reporting/logging from with in a Task

我有一個異步調用,如果給定記錄處理失敗,該調用將引發異常。 該異常被捕獲為聚合異常。 現在,有一個要求,我必須從異步方法中記錄警告消息。 我無法登錄到TextBox / Grid,因為它不允許訪問不同線程上的控件,並且由於我實際上想登錄並繼續執行該任務而無法引發異常。 這是啟動任務的父代碼:

private List<OrganizationUser> GenerateDataList(string importFilePath, int lastUserId = -1)
{
  var resultList = new List<OrganizationUser>();

  // Note: ReadLine is faster than ReadAllLines
  var lineCount = File.ReadLines(importFilePath).Count();
  LogMessage(new LogEntry(String.Format(" - File has {0} lines.", lineCount)));
  var consistancyCounter = 0;

  ResetProgress();

  using (var fs = File.Open(importFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
  {
    using (var bs = new BufferedStream(fs))
    {
      using (var sr = new StreamReader(bs))
      {
        string readLine;
        while ((readLine = sr.ReadLine()) != null)
        {
          if (string.IsNullOrEmpty(readLine) || readLine == "---EOF---")
          {
            break;
          }

          try
          {
            var processLineTask = Task.Run(() => GenerateDataListInternal(nextId++, localReadLine, localConsistancyCounter));
            processLineTask.Wait();

            var result = processLineTask.Result;

            if (result != null)
            {
              resultList.Add(result);
            }
          }
          catch (AggregateException exp)
          {
            if (exp.InnerExceptions.Count == 1 && exp.InnerExceptions.Any(x => x is DataFileBadColumnNumbers || x is DataFileGenerateListException))
            {
              LogMessage(new LogEntry(exp.InnerExceptions[0].Message, LogEntryType.Warning));
            }
            else if (exp.InnerExceptions.Count == 1 && exp.InnerExceptions.Any(x => x is IndexOutOfRangeException))
            {
              LogMessage(new LogEntry(String.Format(" - Data cannot be parsed at line #{0}. Data is: {1}", localConsistancyCounter + 1, localReadLine), LogEntryType.Warning));
            }
            else
            {
              throw;
            }
          }
        }

        if (ProgressBarImport.Value <= ProgressBarImport.Maximum)
        {
          ProgressBarImport.PerformStep();
        }   
      }
    }
  }
}

在上面的代碼中, GenerateDataListInternal是引發異常並且現在需要記錄的方法。

如何從GenerateDataListInternal方法中登錄? 我已經嘗試了委托方法,並且只是掛了應用程序。 我有一個方法登錄到控制台,網格和文本文件(按此順序)。 由於跨線程操作,從異步方法對該方法的任何調用都會失敗。

這已經通過System.IProgress接口和Progress類提供了,其中T可以是任何類,從而使您報告的不僅僅是簡單的進度百分比。

IProgress<T>.Report允許您從異步操作內部報告進度(或其他任何東西),而不必擔心誰會真正處理該報告。

每當您的任務調用.Report時, Progress<T>都會在創建它的線程(例如UI線程)上調用操作和/或引發事件。

.NET Framework Blog中的以下示例顯示了使用IProgress<T>多么容易:

async Task<int> UploadPicturesAsync(List<Image> imageList, IProgress<int> progress)
{
        int totalCount = imageList.Count;
        int processCount = await Task.Run<int>(() =>
        {
            int tempCount = 0;
            foreach (var image in imageList)
            {
                //await the processing and uploading logic here
                int processed = await UploadAndProcessAsync(image);
                if (progress != null)
                {
                    progress.Report((tempCount * 100 / totalCount));
                }
                tempCount++;
            }

            return tempCount;
        });
        return processCount;
}

異步過程從以下代碼開始:

private async void Start_Button_Click(object sender, RoutedEventArgs e)
{
//construct Progress<T>, passing ReportProgress as the Action<T> 
    var progressIndicator = new Progress<int>(ReportProgress);
//call async method
    int uploads=await UploadPicturesAsync(GenerateTestImages(), progressIndicator);
}

請注意, progressIndicator是在UI線程中創建的,因此ReportProgress方法將在UI線程上調用。

更新

從注釋中聽起來,您似乎正在嘗試創建自己的日志記錄解決方案,並且在從多個線程訪問日志文件時遇到問題。

最好的解決方案是使用日志庫,例如log4netNLog或什至.NET的診斷類。 它們都可以在多個線程上正常工作。

IProgress<T>在這里仍然可以提供幫助,因為處理Report事件的委托可以將消息簡單地寫入到您已經在UI線程上創建的日志文件中。

您可以這樣寫:

var progress = new Progress<LogEntry>(entry =>
{
   _logFile.WriteLine("{0} : {1}",entry.EntryType,entry.Message);
});

並從任務內部報告:

var entry=new LogEntry(...);
progress.Report(entry);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM