我目前正在开发一个项目,用于在现有的ASP.Net MVC网站和我公司正在使用的文件托管服务之间建立集成。典型的用例是:
托管服务可以处理并发呼叫,并且我发现在任务中执行每个API调用(参见下面的示例)会导致相当大的改进。
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同时运行任务并不会锁定该站点。
答案 0 :(得分:1)
您应该使用Microsoft的Reactive Framework来实现此目的。它非常适合这种处理。
以下是代码:
IObservable<FileHostResult> query =
from i in identifiers.ToObservable()
from r in Observable.Start(() => GetFileHostResultFromFileHost(i.ExternalIdentifier))
select r;
IList<FileHostResult> results = query.ToList().Wait();
那就是它。它可以在最佳线程数上正确调度代码。
如果您想要等待代码,那么您可以这样做:
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&#34; System.Reactive&#34;然后将using System.Reactive.Linq;
添加到您的代码中。
答案 1 :(得分:0)
如果没有看到其余的源代码,很难给出很好的建议。但根据我所看到的情况,我建议采用以下方法:
(app\db)
这种方法的优点:
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
和AsParallel
为您处理您可能还希望增加有权访问的maximum number个连接。
虽然诚实,但我认为你应该看看根本不需要新Select
的方法 - 可能是使用Async http下载调用你可以运行{ {3}}没有线程的开销。