运行同步方法异步

时间:2015-11-11 08:35:43

标签: c# asynchronous async-await

我有一个迭代对象列表的方法,并且列表中的每个项目都从外部api中获取数据。

有时这可能非常慢(自然),我想将我的所有项目添加到Taks列表,而不是能够同时运行多个线程。这可能没有重写它是异步的吗?今天我正在使用WebClient并同步获取所有内容。

我最初尝试过这样的事情:

public Main() 
{
    List<Task<Model>> taskList = new List<Task<Model>>();
    foreach (var aThing in myThings)
    {
        taskList.Add(GetStuffAsync(aThing));
    }

    List<Model> list = Task.WhenAll(taskList.ToArray()).Result.ToList();
}

public async Task<Model> GetStuffAsync(object aThing)
{
    // Stuff that is all synchronous
    // ...
    return anObject;
}

2 个答案:

答案 0 :(得分:5)

不是在这里使用异步,而是可以使GetStuff成为普通的同步方法,并使用Task.Run创建新任务(通常在多个线程上运行),以便并行发生。您还可以考虑使用Parallel.ForEach之类的内容,它与您当前的Main代码实际上类似。

您的异步方法目前正在执行您想要的操作,因为异步方法至少与第一个await表达式同步运行...在您不喜欢的情况下t有任何await表达式,所以当GetStuffAsync返回时,它已经完成了所有实际工作 - 你没有并行性。

当然,另一种方法是使用您当前的代码,但实际确实使GetStuffAsync异步。

同样值得记住的是,.NET中的HTTP堆栈有per-host connection pool limits - 因此,如果您从同一主机获取多个URL,您可能也想要增加它们,或者您不会得到很多并行性。

答案 1 :(得分:-1)

尝试这个概念:

foreach(var aThing in myThings)
{
    Thread myTask = new Thread(new ParameterizedThreadStart(TaskMethod));
    myTask.Start(aThing);
}

并且必须有一个名为TaskMethod的方法void TaskMethod(object obj)