【问题标题】:Task in synchronous application - IO bound同步应用程序中的任务 - IO 绑定
【发布时间】:2018-11-06 16:18:36
【问题描述】:

我们正在研究一个旧的比较器。

当用户进行研究时,我们会同时调用 10-30 个不同的 Web 服务(REST、SOAP)。太经典了。每个 Web 服务都由我们应用程序中的客户端表示。

所以代码是这样的:

//Get the request list of client to call
clientRqListToCall = BuildRequest(userContext);
List<Task> taskList = new List<Task>();

//Call the different client
Foreach (ClientRequest clientRq in clientRqListToCall) {
    Task task = Task.Run(() => CallClient(clientRq));
    taskList.Add(task);
}
//wait client until timeOut
Task mainWaiterTask = Task.WhenAll(taskList);
mainTask.ConfigureAwait(false);
mainTask.Wait(timeout);

简单。 (不确定是否需要 configureAwait)。每个客户端的响应都存储在ClientRequest的一个字段中,所以我们不使用mainTask.Result(如果客户端超时,我们需要能够继续另一个客户端,并且它们超时很多!客户端调用行为很漂亮类似于fireandforget)。

应用有点旧,我们的搜索引擎是同步的。不同webservice的调用在不同的CallClient callTree中,根据研究上下文,在webservice调用之前会调用5到15个不同的函数。每个网络服务调用都很长(每个 1 到 15 秒)!这一点似乎很重要!这些不是 ping 简单的 ping 请求。

操作/更改?

所以这是一个 I/O 密集型问题,我们知道 Task.Run 非常适合 CPU 密集型问题而不是 I/O,问题是如何让这段代码变得更好?

感谢 Stephen Cleary (http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html),我们阅读了很多关于该主题的不同文章 但是我们不确定我们的选择/路线图,这就是我发布这张票的原因。

  • 我们可以使代码异步,但我们必须重新设计整个 CallClient 调用树(数百个函数)。这是唯一的解决方案吗?当然,我们可以使用 bool 参数 hack (https://msdn.microsoft.com/en-us/magazine/mt238404.aspx) 一个一个地迁移 web 服务。 => 我们必须从最昂贵(以 IO 而言)的 webservice 开始,还是只有 webservice 调用的数量很重要,所以我们应该从最简单的开始? 换句话说,如果我有 1 个大客户,平均响应时间为 10 秒,并且有大量数据,那么我们必须先开始异步吗?或者应该从具有相同数据量的小数据(1-2 秒)开始。我可能是错的,但是一个线程以同步方式锁定,直到 task.run() 完成,所以很明显 10s Task 一直锁定一个线程,但就 I/O 而言,尽快释放一个线程可能会更好。数据下载量重要吗?还是我们应该只考虑网络服务计时器?

  • Task.Run 使用应用程序线程池,我们必须在 .Run(...) 或 Task.Factory.StartNew(..., TaskCreationOptions.LongRunning) 之间进行选择,以便(很多时候) , 创建新线程,因此可能会更好。 => 我使用控制台应用程序对 subjet 进行了一些测试,在所有情况下,.Run() 似乎比 Task.Factory.StartNew 快 25% 到 33%。 当然这是一个预期的结果,但是在一个有 200 个用户的 webapp 上, 我不确定结果是否相同,我担心池已满,并且任务会相互跳转而不会结束。 注意:如果使用startNew,WaitAll(timeout)替换WhenAll。

今天我们平均有 20 到 50 位客户可以同时进行研究。应用程序工作没有大问题,我们没有死锁,但有时我们会看到我们这边的任务执行有些延迟。我们的 Cpu 使用率很低(

我知道有很多关于任务的票,但是很难将它们合并在一起以解决我们的问题。我们还阅读了相互矛盾的建议。

【问题讨论】:

    标签: c# c#-4.0 concurrency io task


    【解决方案1】:

    我之前用过Parallel.ForEach来处理多个I/O操作,上面没有看到。我不确定它会完全处理您需要看到传递到循环中的函数对于每个函数都是相同的。也许再加上一个策略模式/委托,你可以实现你所需要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      • 2016-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多