Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#异步和任务_C# - Fatal编程技术网

C#异步和任务

C#异步和任务,c#,C#,我有一个函数,可以发送请求,从url搜索信息。搜索条件是一个列表,搜索将遍历每个项目,并从url请求信息。为了加快速度,我将列表划分为x个子集,并为每个子集创建一个任务。然后每个子集同时发送3个请求,如下所示: 这是主要的切入点: Search search = new Search(); await Task.Run(() => search.Start()); 启动功能: public void Search() { //Each subset is a List<T&

我有一个函数,可以发送请求,从url搜索信息。搜索条件是一个列表,搜索将遍历每个项目,并从url请求信息。为了加快速度,我将列表划分为x个子集,并为每个子集创建一个任务。然后每个子集同时发送3个请求,如下所示:

这是主要的切入点:

Search search = new Search();
await Task.Run(() => search.Start());
启动功能:

public void Search()
{
    //Each subset is a List<T> ie where T is certain search criteria
    //If originalList.Count = 30 and max items per subset is 10, then subsets will be 3 lists of 10 items each
    var subsets = CreateSubsets(originalList);

    List<Task> tasks = new List<Task>(subsets.Count);
    for (int i = 0; i < subsets.Count; i++)
        tasks.Add(Task.Factory.StartNew(() => SearchSubset(subsets[i]));

    Task.WaitAll(tasks.ToArray());

    foreach (Task task in tasks)
        if (task != null)
            task.Dispose();
}

private void SearchSubset(List<SearchCriteria> subset)
{
    //Checking that i+1 and i+2 is within subset.Count-1 has been omitted
    for (int i = 0; i < subset.Count; i+=3)
    {
        Task[] tasks = {Task.Factory.StartNew(() => SearchCriteria(subset[i])), 
                        Task.Factory.StartNew(() => SearchCriteria(subset[i+1])),
                        Task.Factory.StartNew(() => SearchCriteria(subset[i+2]))};

        //Wait & dispose like above
    } 
}

private void SearchCriteria(SearchCriteria criteria)
{
    //SearchForCriteria uses WebRequest and WebResponse (callback)
    //to query the url and return the response.content

    var results = SearchForCriteria(criteria);

    //process results...
}
公共作废搜索()
{
//每个子集都是一个列表,即T是特定的搜索条件
//如果originalList.Count=30,且每个子集的最大项目数为10,则子集将为3个列表,每个列表包含10个项目
var子集=CreateSubsets(原始列表);
列表任务=新列表(子集计数);
对于(int i=0;iSearchSubset(子集[i]));
Task.WaitAll(tasks.ToArray());
foreach(任务中的任务)
如果(任务!=null)
task.Dispose();
}
私有void搜索子集(列表子集)
{
//检查i+1和i+2是否在子集内。已忽略计数-1
对于(int i=0;iSearchCriteria(子集[i]),
Task.Factory.StartNew(()=>SearchCriteria(子集[i+1])),
Task.Factory.StartNew(()=>SearchCriteria(子集[i+2]))};
//等待并按上述方式处理
} 
}
专用无效搜索条件(搜索条件)
{
//SearchForCriteria使用WebRequest和WebResponse(回调)
//查询url并返回response.content
var结果=搜索标准(标准);
//过程结果。。。
}

上面的代码工作得很好,搜索速度也很快。但是,上面的代码是否产生了太多的开销,是否有更干净(或更简单)的代码实现相同结果的方法?

这不是最有效的方法,但如果这是针对桌面应用程序,效率并不是您最关心的问题。因此,除非您实际看到这段代码的性能下降,否则您不应该更改它

也就是说,我会以不同的方式处理这个问题

您正在使用TPL来并行化I/O绑定操作。您正在使用最复杂的类型;正如Jeff Mercado所评论的,如果您使用更高级别的并行化抽象(例如),那么您的代码将更简单、更高效

然而,任何并行方法都会阻塞线程池线程,从而浪费线程池线程。由于这是I/O绑定的,我建议使用
async
/
wait
使它们并发

如果要执行简单的节流,可以使用
信号量lim
。我认为除了子集之外,您不需要像这样进行节流,但是如果您想要一个与现有代码等价的
async
,它将如下所示:

public Task SearchAsync()
{
  var subsets = CreateSubsets(originalList);
 return Task.WhenAll(subsets.Select(subset => SearchSubsetAsync(subset)));
}

private Task SearchSubsetAsync(List<SearchCriteria> subset)
{
  var semaphore = new SemaphoreSlim(3);
  return Task.WhenAll(subset.Select(criteria => SearchCriteriaAsync(criteria, semaphore)));
}

private async Task SearchCriteriaAsync(SearchCriteria criteria, SemaphoreSlim semaphore)
{
  await semaphore.WaitAsync();
  try
  {
    // SearchForCriteriaAsync uses HttpClient (async).
    var results = await SearchForCriteriaAsync(criteria);

    // Consider returning results rather than processing them here.
  }
  finally
  {
    semaphore.Release();
  }
}
公共任务SearchAsync()
{
var子集=CreateSubsets(原始列表);
返回Task.WhenAll(subsets.Select(subset=>SearchSubsetAsync(subset));
}
专用任务SearchSubsetAsync(列表子集)
{
var信号量=新信号量lim(3);
返回Task.WhenAll(subset.Select(criteria=>SearchCriteriaAsync(criteria,semaphore));
}
专用异步任务SearchCriteriaAsync(SearchCriteria条件,信号量lim信号量)
{
wait semaphore.WaitAsync();
尝试
{
//SearchForCriteriaAsync使用HttpClient(异步)。
var结果=等待SearchForCriteriaAsync(标准);
/考虑返回结果而不是在这里处理它们。
}
最后
{
semaphore.Release();
}
}

您不需要处理任务,这样可以简化代码。在我看来,您可以/应该使用TPL进行搜索。您正在进行的分区和调度都将由您来处理。如果必须将上面的代码更改为使用TPL,它会是什么样子?