登录异步方法的正确方法

时间:2016-05-31 09:38:55

标签: c# linq async-await win-universal-app

关于以下代码的两个问题:

  • 这个实现是异步方法的实现吗?
  • 是否正确实现了记录删除文件时可能出现的异常?

    public static async Task DeleteFiles(StorageFolder folder, Regex mask, LoggingChannel logger)
    {
        var results = (from file in await folder.GetFilesAsync() where mask.IsMatch(file.Name) select file).Select(async f => await f.DeleteAsync());
        await Task.WhenAll(results);
        foreach (var failed in results.Where(r => r.Exception != null)) logger.LogMessage(failed.Exception.ToString(), LoggingLevel.Warning);
    }
    

它更好(对吧?)方式:

    public static async Task DeleteFiles(StorageFolder folder, Regex mask, LoggingChannel logger)
    {
        foreach(var f in (await folder.GetFilesAsync()).Where( f => mask.IsMatch(f.Name)))
        {
            try
            {
                await f.DeleteAsync();
            }
            catch(Exception ex)
            {
                logger.LogMessage(ex.ToString(), LoggingLevel.Warning);
            }
        }

    }

2 个答案:

答案 0 :(得分:1)

第二个实现将逐个删除文件,因为将等待每次删除以提供同步体验。所以第一次实现可能会更快。

正确实施:

public static async Task DeleteFilesAsync(StorageFolder folder, Regex mask, LoggingChannel logger)
{
    var results = (from file in await folder.GetFilesAsync() where mask.IsMatch(file.Name) select file).Select(f => f.DeleteAsync());
    try
    {    
        await Task.WhenAll(results);
    }
    catch(Exception ex)
    {
        foreach (var failed in results.Where(r => r.Exception != null)) logger.LogMessage(failed.Exception.ToString(), LoggingLevel.Warning);
    }
}

我认为应始终在代码中明确标识异常处理,因此尝试使用try / catch块。

记住。选择获取任务,我删除了不必要的异步/等待那里。

或执行Task.WaitAll(results)并抓住AggregateException

另见Why doesn't await on Task.WhenAll throw an AggregateException?

答案 1 :(得分:0)

另一种可以并行进行日志记录的方法。这是使用和DataFlowBlock。

var actBlock = new ActionBlock<Task>(t => { var tsk = t.IsFaulted ? loggingTask : dummyTask; },new ExecutionDataflowBlockOptions
{
    MaxDegreeOfParallelism = configurableValue
});

var obsr = actBlock.AsObserver();
FileDeletionTasks.ToObservable().Subscribe(t => obsr.OnNext(t), async ex => await loggingTask);
actBlock.Complete();