C# Task.Run() 与 C++ std::async()

标签 c# c++ concurrency

我在我的 Mac 上运行 2 个相似的代码示例,一个是 C++,另一个是 C#。 2 个并行执行的简单任务(或者至少我希望它们这样做),一个在循环中打印“+”,另一个在循环中打印“-”。我原以为 2 个样本的输出非常相似,但出乎我的意料,它们有很大的不同。

C++ 似乎真正并行地运行任务。我可以在每次运行时看到 +- 很好地交替,但 C# 似乎运行一个任务一段时间,然后切换到另一个任务并运行一段时间。像这样:

C++: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
C# : ++++++++++---------++++++------

我知道不能对并行线程的运行方式做出假设,我很好奇 C++ 始终如一地产生如此好的结果。

感谢您的宝贵时间!

C#:

using System;
using System.Threading.Tasks;

public class ConcurrentTasks
{
    public static void Main(String[] args)
    {
        var task1 = Task.Run(()=>DemoTask("+"));
        var task2 = Task.Run(()=>DemoTask("-"));
        var res1 = task1.Result;
        var res2 = task2.Result;
        Console.WriteLine("\nResults:");
        Console.WriteLine(res1);
        Console.WriteLine(res2);
    }

    private static String DemoTask(String label)
    {
        for (int i = 0; i < 1000; i++)
        {
            Console.Write(label);
        }

        return label + " result";
    }
}

// mcs ConcurrentTasks.cs
// mono ConcurrentTasks.exe

C++:

#include <iostream>
#include <sstream>
#include <future>
using namespace std;

string demoTask(char label)
{
    for (int i = 0; i < 1000; i++)
    {
        cout << label;
    }

    stringstream ss;
    ss << label;
    ss << " result";
    return ss.str();
}

int main()
{
    auto task1 = async(demoTask, '+');
    auto task2 = async(demoTask, '-');
    auto res1 = task1.get();
    auto res2 = task2.get();
    cout << endl << "Results:" << endl;
    cout << res1 << endl;
    cout << res2 << endl;
    return 0;
}

// g++ --std=c++14 -Wall ConcurrentTasks.cpp -o ConcurrentTasks.exe
// ./ConcurrentTasks.exe

编辑:我已经将 C# 示例更改为使用裸线程,结果是一样的。

带线程的 C#:

using System;
using System.Threading;

public class ConcurrentTasks
{
    public static void Main(String[] args)
    {
        var t1 = new Thread(() => DemoTask("+"));
        var t2 = new Thread(() => DemoTask("-"));
        t1.Start();
        t2.Start();
    }

    private static String DemoTask(String label)
    {
        for (int i = 0; i < 1000; i++)
        {
            Console.Write(label);
        }

        return label + " result";
    }
}

最佳答案

粒度可能是原因之一。 TPL 可能具有 调度任务的粒度,但 C++ async 实现可能具有精细 粒度。这实质上意味着 C++ 将花费更多时间,因为仅用于处理 +- 它会在两者之间安排另一个任务。

另一个原因可能是 coutConsole 是如何实现输出流的。如何锁定以在屏幕上呈现某些内容?正在实现任何缓冲吗?你看,Console.Write 可能正在缓冲,然后在一段时间后打印,但 cout 可能只是立即打印。

因此,您应该做其他事情,而不是依赖于语言的底层 I/O - 可以将字符放在一个共享静态大小的数组中,共享 int 作为共享数组的索引(它们是原子的,不需要锁 用最轻量级的同步原语如读写锁来锁定它)。不,不要使用 vectorArray - 因为在那种情况下,您再次依赖您不知道的东西!

在两种情况下都使用 Release 构建,并尽可能使用相同的优化选项。另外,确保您在同一台机器上运行它们。

关于C# Task.Run() 与 C++ std::async(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37242434/

相关文章:

c# - 如何使用 PCL 创建目录

c# - 如何删除逗号分隔的重复字符串值并获取最后两个值

构造函数中的 C++ 引用

sql-server - 事务隔离级别和子查询

java - 如何在我的代码中实现线程安全

c# - 接受 List<T> 的通用方法

c# - 创建树数据结构

c++ - 我需要在此代码中调用 SafeArrayUnLock 吗?

c++ - 关于 : Child Class in a Array C++

java - 在 Java EE 应用程序中锁定