如何使用任务或并行调用以正确的顺序获得翻译结果?

时间:2017-09-06 03:42:26

标签: c# multithreading parallel-processing

private string trdoc(string str)
{
    var listOfActions = new List<Action>();

    string alltrdoc = "";
    string doc = str;
    var alldoc = doc.Split('\n');
    foreach(string tt in alldoc)
    {
        //alltrdoc = alltrdoc + translate(tt) + '\n';//I can get the translated sentences in order but it's not multithread so it is slow.

        listOfActions.Add(() => alltrdoc = alltrdoc + translate(tt) + '\n');//I can't get the translated sentences in order.

    }
    int paral = 4;
    if (paral <= 0) { paral = 4; }
    var options = new ParallelOptions { MaxDegreeOfParallelism = paral };
    Parallel.Invoke(options, listOfActions.ToArray());

    saveposcdic();

    return alltrdoc;
}

translate(tt)应生成翻译后的字符串。

我一直在努力翻译。我遇到了这个问题。

如果我使用没有,task或parallel.invoke的代码,那么我会以正确的顺序翻译文档。但是,如果我像上面那样运行parallel.invoke,我会把这些句子搞得搞乱。

如何使用task或parallel.invoke以正确的顺序获取翻译的文档?

我想在列表中添加带有数字的翻译句子,然后在完成所有任务后对列表进行排序,然后拆分句子并重新排列,但我认为必须有更好的方法。

以下代码有效但不平行。

private string trdoc(string str)
{
   string alltrdoc = "";
   string doc = str;
   var alldoc = doc.Split('\n');

   Task t = Task.Factory.StartNew(() => {
   foreach (string tt in alldoc)
   {
    alltrdoc = alltrdoc + translate(tt) + '\n';
   }
   });

   t.Wait();

   saveposcdic();

   return alltrdoc;
}

3 个答案:

答案 0 :(得分:3)

原因是对的。你需要谨慎地处理并行性问题 你可以将它删除到linq。

var translatedStrings = alldoc
    .AsParallel()
    .WithDegreeOfParallelism(paral)
    .AsOrdered()
    .Select(tt => translate(tt));

var alltrdoc = string.Join("\n", translatedStrings);  

这里有两个关键方法:
AsParallel select使trdoc执行并行AsOrdered,这将保持行的原始顺序。

您的第二个Parallel.Invoke实施并不平行,因为您将所有工作放在一个任务中。这就像仅使用Action

运行{ "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe", "terminal.integrated.shellArgs.windows": ["-lic", "cd $OLDPWD; exec bash"], } 一样

答案 1 :(得分:0)

我怀疑你没有在你的闭包中捕获循环变量。尝试将循环更改为:

foreach (string tt in alldoc)
{
    string local_tt = tt;
    listOfActions.Add(() => alltrdoc = alltrdoc + translate(local_tt) + '\n');
}

您遇到的另一个问题是您尝试使用多个线程更新alltrdoc的单个值。它不会像那样工作。你真的应该考虑重构这段代码。

你最好像这样编写整个方法:

private string trdoc(string str)
{
    return String.Join(Environment.NewLine, str.Split('\n').AsParallel().Select(x => translate(x)));
}

答案 2 :(得分:0)

private string trdoc(string str)
{
    var alldoc = str.Split('\n');            
    string[] alltrdoc1 = new string[alldoc.Length];

    Parallel.For(0, alldoc.Length,
    index => {

        alltrdoc1[index] = translate(alldoc[index]);

    });

    string alltrdoc = string.Join("\n", alltrdoc1);

    saveposcdic();

    return alltrdoc;
}

我已经使用了这段代码了。所有句子都以正确的顺序显示。我仍然不知道为什么Enigmativity的答案没有达到预期的效果。