首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >对外部服务的并发调用

对外部服务的并发调用
EN

Stack Overflow用户
提问于 2018-06-09 05:14:51
回答 2查看 64关注 0票数 0

我目前正在做一个项目,在现有的ASP.Net MVC网站和我的公司正在使用的文件托管服务之间建立一个集成。典型的用例是:

  1. 用户请求一个或多个文件
  2. 控制器对文件主机API进行一次调用
  3. 文件主机将文件数据返回给控制器
  4. 控制器返回文件结果

托管服务可以处理并发调用,我发现在任务中执行每个API调用(参见下面的示例)会带来相当大的改进。

代码语言:javascript
复制
private void RetrieveDocuments(DocumentIdentifier[] identifiers, List<FileHostResult> results)
{
    var tasks = identifiers.Select(x => RetrieveDocument(results, x)).ToArray();
    Task.WaitAll(tasks);
}

private Task RetrieveDocument(List<FileHostResult> results, DocumentIdentifier x)
{
    return Task.Run(() =>
    {
        var result = GetFileHostResultFromFileHost(x.ExternalIdentifier);
        lock (results)
        {
            results.Add(result);
        }
    });
}

我的问题是,是否有更好的方法来做到这一点,或者是否有任何潜在的陷阱,我可能会遇到?(例如,锁定服务器资源等)。

编辑1:我没有发布GetFileHostResultFromFileHost的代码,因为我实际上没有任何权限来更改它。它基本上是一个在库中实现的方法调用,我无法更改。

编辑2:澄清。我主要关心的是避免损害网站当前的用户体验。为此,我希望确保在ASP.net mvc之外并发运行任务不会锁定站点。

EN

回答 2

Stack Overflow用户

发布于 2018-06-09 12:17:20

为此,您应该使用Microsoft的Reactive Framework。它非常适合于这种处理。

代码如下:

代码语言:javascript
复制
IObservable<FileHostResult> query =
    from i in identifiers.ToObservable()
    from r in Observable.Start(() => GetFileHostResultFromFileHost(i.ExternalIdentifier))
    select r;

IList<FileHostResult> results = query.ToList().Wait();

就这样。它适当地将代码安排在最优的线程数上。

如果你想要可等待的代码,你可以这样做:

代码语言:javascript
复制
IObservable<FileHostResult> query =
    from i in identifiers.ToObservable()
    from r in Observable.Start(() => GetFileHostResultFromFileHost(i.ExternalIdentifier))
    select r;

IList<FileHostResult> results = await query.ToList();

它真的非常简单,很容易编码。

NuGet "System.Reactive“,然后将using System.Reactive.Linq;添加到代码中。

票数 1
EN

Stack Overflow用户

发布于 2018-06-09 05:51:24

如果不看其余的源代码,就很难给出好的建议。但根据我所看到的,我会建议这样一种方法:

代码语言:javascript
复制
private void RetrieveDocuments(DocumentIdentifier[] identifiers, List<FileHostResult> results)
{
    results.AddRange(identifiers.AsParallel().Select(x => RetrieveDocument(x)));
}

private FileHostResult RetrieveDocument(DocumentIdentifier x)
{
    var result = GetFileHostResultFromFileHost(x.ExternalIdentifier);
    return result;
}

这种方法的优点是:

  • 不显式使用Task.Run -让AsParallel为您处理。
  • 无需锁定results列表-让AsParallelSelect为您处理<代码>H210<代码>F211

您可能还希望增加您有权访问的连接的。

不过老实说,我认为你应该考虑那些根本不需要新的并行Task**s的方法--可能是通过使用http下载调用,这样你就可以在没有线程开销的情况下运行 [in parallel](https://stackoverflow.com/questions/19383910/paralell-foreach-with-httpclient-and-continuewith) 。**

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50768473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档