如何最好地将异步等待应用于foreach循环?

时间:2017-12-16 17:38:33

标签: c# asynchronous

我是C#的亲戚,他是我第一次尝试异步方法。我已经整理了一个简单的练习应用程序(WPF MVVM),它列出了我系统上的性能计数器。我现在花了几个小时阅读通过谷歌发现的问题和帖子。根据他们中的几个,我做错了,但我做了几次尝试,使下面的代码更好。不可否认,我对很多文档和帮助指南感到困惑,因为它们区分了异步和任务。 This guide提供了一些帮助,但我很难将其应用到我的代码中。

守则

public async void UpdateCounters(PerformanceCounterCategory category)
    {
        await Task.Run(() =>
        {
            Counters = GetCounters(category);
        });
    }

    private ObservableCollection<PerformanceCounter> GetCounters(PerformanceCounterCategory category)
    {
        var countersList = new ObservableCollection<PerformanceCounter>();
        if(category != null)
        {
            var instances = category.GetInstanceNames().OrderBy(ins => ins);
            if(instances.Any())
            {
                foreach(var instance in instances)
                {
                    if(category.InstanceExists(instance))
                    {
                        //this is time consuming segment when I'm listing something like "Process" counters
                        var counters = category.GetCounters(instance);
                        foreach(var counter in counters)
                            countersList.Add(counter);
                    }
                }
            }
        }
        return countersList;
    }

我尝试将该方法转换为异步方法。像这样......

private async Task<List<PerformanceCounter>> GetCounters(PerformanceCounterCategory category)
        {   //Changes receiving expression to Counter = new ObservableCollection(GetCounters(category));
            var countersList = new List<PerformanceCounter>();
//But I couldn't figure out where to put the await

我最终想要展示等待......&#34;或者UI上的其他一些提示/进度指示器,但我想以正确的方式进行。我目前的代码阻止它无响应,但这是关于所有。

这一切都应该是单一的异步方法,可能就像我已经完成了更好的编码,或者我应该在foreach中创建一个任务列表。 (我也拍了拍,但这是一次史诗般的失败)。

1 个答案:

答案 0 :(得分:1)

执行以下操作

private async Task<List<PerformanceCounter>> GetCounters(PerformanceCounterCategory category)
{   
  List<Task<PerformanceCounter>> lstTask = new     
                     List<Task<PerformanceCounter>>();
  List<PerformanceCounter> counters = new List<PerformanceCounter>();

  //your code 
 foreach(var instance in instances)
 {
   lstTask.Add( Task.Factory.StartNew(()=> return    
  category.GetCounters(instance)));
 }

  try {
     await Task.WhenAll(lstTask.ToArray());
  }
  catch {}  
  foreach(var task in lstTask )
  {
    if(task.Status != TaskStatus.Faulted)
       counters.Add(task.Result);
    else 
        //log error task.Exception
  }

   return counters ;
}