在每个方法的自定义核心数/线程数上并行执行两个方法

时间:2018-08-25 09:59:37

标签: c# multithreading task-parallel-library

有没有一种方法可以指定每个方法使用的内核/线程数,而不会阻塞它们。 例: 我有方法A和方法B。 方法A将被调用50次,方法B也将被调用。

假设我有一个16核的CPU。 我想委托它为方法A使用并行的2个线程,为方法B使用4个线程,而不阻塞它们。 我已经尝试过使用信号量,但是在执行任务后它们会阻塞并释放。

这是一些示例代码: 注意:threadService方法仅调用Thread.Sleep 3秒钟

static void Main(string[] args)
    {
        ThreadService threadService = new ThreadService();

        for (int i = 0; i < 5; i++)
        {
            Task t = Task.Run(() => threadService.RunFirstMethod());
        }

        for (int i = 0; i < 5; i++)
        {
            Task t = Task.Run(() => threadService.RunSecondMethod());
        }

        Console.ReadLine();
    }

也许这不是一个好主意...?任何帮助或建议,将不胜感激。 谢谢。

首次尝试使用信号灯(不行):

static void Main(string[] args)
    {
        ThreadService threadService = new ThreadService();

        Semaphore semaphoreFirstMethod = new Semaphore(2, 2);
        for (int i = 0; i < 5; i++)
        {
            semaphoreFirstMethod.WaitOne();
            Task t = Task.Run(() => threadService.RunFirstMethod()).ContinueWith(s => semaphoreFirstMethod.Release());
        }

        Semaphore semaphoreSecondMethod = new Semaphore(2,2);
        for (int i = 0; i < 5; i++)
        {
            semaphoreSecondMethod.WaitOne();
            Task t = Task.Run(() => threadService.RunSecondMethod()).ContinueWith(s => semaphoreSecondMethod.Release());
        }
        Console.ReadLine();
    }

以下是结果:

   2018-08-25 15:34:17.7259 INFO RunFirstMethod()
2018-08-25 15:34:17.7259 INFO RunFirstMethod()
2018-08-25 15:34:19.7691 INFO RunFirstMethod()
2018-08-25 15:34:19.7691 INFO RunFirstMethod()
2018-08-25 15:34:21.7775 INFO RunFirstMethod()
2018-08-25 15:34:21.7775 INFO RunSecondMethod()
2018-08-25 15:34:21.7775 INFO RunSecondMethod()
2018-08-25 15:34:23.8053 INFO RunSecondMethod()
2018-08-25 15:34:23.8053 INFO RunSecondMethod()
2018-08-25 15:34:25.8211 INFO RunSecondMethod()

@mjwills建议在sempahores上发布代码后,我发现我没有做应该做的事情, 信号量的第二种实现:

static void Main(string[] args)
    {
        ThreadService threadService = new ThreadService();

        Task.Run(() =>
        {
            Semaphore semaphore = new Semaphore(2, 2);
            for (int i = 0; i < 5; i++)
            {
                semaphore.WaitOne();
                Task t = Task.Run(() => threadService.RunFirstMethod()).ContinueWith(s => semaphore.Release());
            }
        });

        Task.Run(() =>
        {
            Semaphore semaphore = new Semaphore(2, 2);
            for (int i = 0; i < 5; i++)
            {
                semaphore.WaitOne();
                Task t = Task.Run(() => threadService.RunSecondMethod()).ContinueWith(s => semaphore.Release());
            }
        });
        Console.ReadLine();
    }

第二个结果(对我来说还可以):

    2018-08-25 15:36:01.0845 INFO RunSecondMethod()
2018-08-25 15:36:01.0855 INFO RunFirstMethod()
2018-08-25 15:36:02.0863 INFO RunFirstMethod()
2018-08-25 15:36:03.0783 INFO RunSecondMethod()
2018-08-25 15:36:03.1386 INFO RunSecondMethod()
2018-08-25 15:36:03.1386 INFO RunFirstMethod()
2018-08-25 15:36:04.0938 INFO RunFirstMethod()
2018-08-25 15:36:05.0877 INFO RunSecondMethod()
2018-08-25 15:36:05.1547 INFO RunSecondMethod()
2018-08-25 15:36:05.1677 INFO RunFirstMethod()

2 个答案:

答案 0 :(得分:1)

向所有人致以帮助。我已经通过运行两个任务来完成了解决方案。我需要2种方法来并行运行并控制每个方法的线程数) 线程数由信号量控制。 示例:

AFTER INSERT

答案 1 :(得分:0)

最简单的方法是添加一些调度逻辑,这些逻辑将根据线程逻辑索引决定执行哪种方法:

var threadService = new ThreadService();
Parallel.For(
    0, 6,
    index =>
    {
        if (index < 4)
            threadService.RunFirstMethod();
        else
            threadService.RunSecondMethod();
    });

但是,这不能保证方法将在同一内核上独家执行。为此,您需要指定线程-CPU亲和力,这对于.NET来说有点棘手,因为它在系统线程(仅是可以应用CPU亲和力的线程)之上使用自己的线程。 good article此处说明了如何通过外部呼叫完成此操作。