【问题标题】:.ToListAsync() vs .ToList() + Task.Run.ToListAsync() 与 .ToList() + Task.Run
【发布时间】:2016-07-18 19:35:30
【问题描述】:

我有一个 WPF 应用程序。

数据从存储库带到 ViewModel。检索数据的更好方法是什么:

方法一:

在存储库中:

public List<LogDetail> GetLogsOfTypeForCase(int caseId, LoggType logType)
    {
        using (var ctx = new SidraEntitiesNoChangesDetection())
        {
            var logs = (from l in ctx.Loggs
                where l.log_fk_caseid == caseId && l.log_operation == logType.ToString()
                select new LogDetail()
                {
                    ColumnName = l.log_columnname,
                    DateAndTime = l.log_dateandtime,
                    IdentificationDetail = l.log_identificationDetail,
                    NewValue = l.log_new_value,
                    OldValue = l.log_old_value,
                    TableName = l.log_tablename,
                    UserCode = l.User.usr_code
                }).ToList();

            return logs;
        }
    }

在 ViewModel 中:

await Task.Run(
            () =>
            {
                if (false == this.CancellationTokenSource.IsCancellationRequested)
                {
                    this.CaseLogs = this.dataAdapter.GetLogsOfTypeForCase(this.CaseId, LoggType.S);
                }

            },
            this.CancellationTokenSource.Token
            );

方法二

在存储库中:

public async Task<List<LogDetail>> GetLogsOfTypeForCase(int caseId, LoggType logType)
    {
        using (var ctx = new SidraEntitiesNoChangesDetection())
        {
            var logs = await (from l in ctx.Loggs
                where l.log_fk_caseid == caseId && l.log_operation == logType.ToString()
                select new LogDetail()
                {
                    ColumnName = l.log_columnname,
                    DateAndTime = l.log_dateandtime,
                    IdentificationDetail = l.log_identificationDetail,
                    NewValue = l.log_new_value,
                    OldValue = l.log_old_value,
                    TableName = l.log_tablename,
                    UserCode = l.User.usr_code
                }).ToListAsync();

            return logs;
        }
    }

在 ViewModel 中

protected override async void Load()
    {
           if (false == this.CancellationTokenSource.IsCancellationRequested)
           {
               this.CaseLogs = await this.dataAdapter.GetLogsOfTypeForCase(this.CaseId, LoggType.S);
           }
     }

根据我的阅读,方法 1 是首选,但有什么优势?

【问题讨论】:

  • 谁说方法 1 更可取,他们的证据是什么?
  • 如果你读过其中一本是首选,他们肯定也说为什么?如果您正在阅读有人说某事更好而不是解释,请继续阅读下一篇文章。
  • 另外,不管他们是谁,你可能永远都不应该听他们的。他们显然不明白任务并行库是如何工作的……

标签: c# wpf async-await


【解决方案1】:

方法 2 更可取,因为它使用的线程少。

它也可以(经过一些修改)正确地支持取消:

public async Task<List<LogDetail>> GetLogsOfTypeForCase(int caseId, LoggType logType, CancellationToken token)
{
  ...
        }).ToListAsync(token);
  ...
}

protected override async void Load()
{
  this.CaseLogs = await this.dataAdapter.GetLogsOfTypeForCase(this.CaseId, LoggType.S, this.CancellationTokenSource.Token);
}

【讨论】:

    【解决方案2】:

    方法 2。这些方法的异步版本为您完成了所有“繁重的工作”,这就是它们的设计目的。 Task.Run() 是一个繁重的进程调用,需要你自己处理所有潜在的错误和故障,这里不需要大锤,只需要一个轻量级的整理锤。

    我的意思是您正在尝试创建框架已经为您完成的工作,这就是要使用异步调用的地方,那么为什么不直接使用它们呢?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-04
      • 2022-06-11
      • 2022-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多