多线程转换
本文关键字:转换 多线程 | 更新日期: 2023-09-27 18:13:35
下面的循环将英语单词"Welcome"翻译成其他几种语言。
var result = "";
foreach (var toLanguage in OtherLanguages)
{
result += LanguageUtils.Translate("Welcome", English, toLanguage);
}
return result;
languageutil . translate()是一个使用Microsoft Translator V2引擎的静态方法。到目前为止一切都很好。除了表演。
我想知道我是否可以通过在循环中使用多个线程来加快速度。因此,与其翻译一种语言接着另一种语言(就像我做的那样),我不如同时运行多个翻译。
现在,我读了一些关于多线程的帖子和教程(例如http://www.albahari.com/threading/),但说实话,我毕竟很困惑。这是我第一次处理多线程…这可能是最后一次了。所以我希望如果有任何有经验的人可以帮助我一些代码,告诉我如何将我的给定代码片段转换成多线程方法。
非常感谢!
在。net 4中使用parallel linq:
return OtherLanguages.AsParallel()
.Select(toLanguage => LanguageUtils.Translate("Welcome", English, toLanguage));
ConcurrentBag<string> results = new ConcurrentBag<string>();
Parallel.ForEach(OtherLanguages,toLanguage =>
{
results.Add(LanguageUtils.Translate("Welcome", English, toLanguage));
});
或
ConcurrentDictionary<string,string> results = new ConcurrentDictionary<string,string>();
Parallel.ForEach(OtherLanguages, toLanguage =>
{
results.TryAdd(toLanguage, LanguageUtils.Translate("Welcome", English, toLanguage));
});
在我自己的编辑和翻译字符串资源的免费工具(这个)中,我提供了谷歌翻译(2011年12月停止)和微软必应翻译的两个接口。
从我自己的经验和用户反馈来看,当涉及到过多的请求和/或伪垃圾邮件检测时,Bing是相当暴躁的。
所以我几乎假设你可以在你的代码中做复杂的多线程结构,仍然一无所获,因为你会收到"太多的请求"和类似的异常。
另一种方法是建立自己的查找数据库(内存中的或持久的,根据最适合您的需求),并首先从数据库中查找后续翻译,如果在那里找不到,则转到Bing。
使用。net 4.0可以做到:
<子> <罢工>罢工> 子>
volatile StringBuilder result = new StringBuilder();
void Magic()
{
Parallel.ForEach(OtherLanguages, toLanguage =>
{
var resultIn = result;
var txt = LanguageUtils.Translate("Welcome", English, toLanguage);
do Thread.SpinWait(25);
while (Interlocked.CompareExchange(ref result, result.Append(txt), resultIn) != result);
});
}
罢工更新:不要使用上面的代码
代码是不安全的,因为result.Append
在没有适当锁定的情况下修改了result
引用对象。此外,因为Append
返回相同的StringBuilder引用,Interlocked.CompareExchange
实际上不做任何事情,除了可能导致对Append的调用被重复。
上面的代码引入了一个巨大的性能瓶颈,因为result.Append(txt)
需要在CompareExchange
被调用之前求值。因此,每次线程必须旋转时,它也必须再次计算result.Append(txt)
。
@sehe:
建议的替代方案string.Join(", ", langs.AsParallel().Select(l => Translate("Welcome", English, l)));