【问题标题】:task not return result as expected任务未按预期返回结果
【发布时间】:2018-04-04 10:09:11
【问题描述】:

我正在尝试提高程序的执行速度。我使用该任务使其同时运行。以下是我的原始代码:

StringBuilder expression = new StringBuilder(1024);
int count = table.Rows.Count;
for (int i = 0; i < count; i++)
{                   
        string result = GetResult(companyID);                            
        expression.Append(result);
}   

然后我改成这样:

StringBuilder expression = new StringBuilder(1024);
int count = table.Rows.Count;
for (int i = 0; i < count; i++)
{
   try
    {
        Task task1 = Task.Factory.StartNew(() =>
        {
            string result = GetResult(companyID);                                                        
            expression.Append(result);
        });
    }
    catch (Exception ex) {
    }
} 

但是,结果不一样。怎样才能使使用任务的结果相同?

【问题讨论】:

  • 您的期望和收获是什么?
  • 那么现在您的append 将不再是连续的?如果getresult 是导致您悲伤的原因,请查看DataFlow 或简单地将结果放入ConcurrentQueue 然后附加在一起。
  • 任务不能保证按照它们创建的顺序完成,所以如果你将所有内容附加到同一个StringBuilder,内容很可能会出现乱序,如果它甚至可以工作的话根本——StringBuilder 不是线程安全的。
  • OP,您的代码示例准确吗?似乎你一遍又一遍地用同样的论点打电话给GetResult()。 CompanyID 在哪里声明以及如何填充?
  • 什么是GetResult(companyID) 它返回什么,为什么companyID 总是一样的,你介意以任何特定顺序的结果吗? stringbuilder 也不是线程安全的,谁知道内部缓冲区会做什么

标签: c# concurrency task-parallel-library


【解决方案1】:

简化你的情况:

List<string> Outputs = new List<string>();

for(int i=0; i< 100; i++)
{
    Outputs.Add($"Hello World: {i}");
}

这里,输出是带有 Hello World: 1, 2, .... 的字符串列表:

您的并行化方式 - 不能保证相同的顺序(因为这就是并行化,您不能说哪个任务先完成)。

如果您期望与顺序逻辑相同的输出,但希望并行执行,您可以执行以下操作:

Parallel.For(0, 100, (i) =>
{
    Outputs.Insert(i, $"Hello World: {i}");
});

注意,循环体中的代码 - 在预期索引处插入字符串。这将创建预期的输出。

【讨论】:

  • 谢谢,Prateek,如果我想在循环中附加一些东西,我该怎么办。比如 Outputs.append(i, "abc"), Outputs.append(i, "cde")。这意味着输出的不止一项操作。我可以这样做吗?
  • @want_to_be_calm - List 没有附加。我猜您正在考虑使用 StringBuilder - 它或多或少类似于 String.Append。你不能保证追加会发生在哪里..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 2011-08-09
  • 2010-09-22
  • 2021-05-17
相关资源
最近更新 更多