让用户选择使用多少个线程?

4

我正在尝试制作一个C#工具,用户可以选择同时执行的线程数。例如,他在threadsTextBox中输入“10”,当他点击startButton时,程序将启动,并在10个线程上执行所需的任务。

这是我目前为3个线程编写的代码,但我不知道如何让用户能够选择程序使用多少个线程。

static void Main(string[] args)
{
    Task task1 = Task.Factory.StartNew(() => doStuff());
    Task task2 = Task.Factory.StartNew(() => doStuff());
    Task task3 = Task.Factory.StartNew(() => doStuff());

    Task.WaitAll(task1, task2, task3);
            Console.WriteLine("Done !");
}

static void doStuff()
{
    // do stuff here
}

预先感谢你的帮助。


5
不要这样做。用户选择不当。使用任务并行库,并让它决定使用多少并行性。它擅长这个。通常情况下,您希望添加线程,直到每个处理器正好为一个线程提供服务,并且这些线程始终以100%的效率运行;当给定CPU密集型任务时,TPL会尝试调整以满足这些条件。 - Eric Lippert
3
我注意到正确使用线程是现代编程中最难的任务之一,而你在让用户输入数字方面似乎存在困难,这表明你是初学者。这可能不是一个适合初学者的任务。 - Eric Lippert
你还应该记住,除非doStuff是处理器密集型的,否则你不会从多个任务/线程中获得巨大的好处。你应该使用不同数量的运行任务来测量处理时间,并查看您是否获得任何好处。 - Enigmativity
3个回答

3
这似乎是数组的理想用法:
static void Main(string[] args) {
    var tasks = new Task[n];
    for (int j1 = 0; j1 < n; ++j1)
        tasks[j1] = Task.Factory.StartNew(() => doStuff());

    Task.WaitAll(tasks);
            Console.WriteLine("Done !");
}

谢谢您的快速回复,所以如果我理解正确,'j' 将是用户选择的线程数,对吗? - Stéphanie Autire
不,n是线程数(也是数组元素数)。没有j - NetMage
非常感谢,我的程序需要读取文本文件的每一行并为每行启动一个线程,假设文本文件包含100行,则线程将继续创建,并且程序仅在执行所有行的任务后才会停止,如果用户选择10个线程,它只会读取前10行吗?谢谢。 - Stéphanie Autire
这将取决于您如何编写问题的其余部分。 - NetMage
我要提出另一个问题。 - Stéphanie Autire
2
一个任务并不是一个线程的1:1对应关系。你所做的只是限制同时创建的任务数量而不是线程数量。你可能会启动4个任务,但由于CPU规格,只有2个任务同时运行。https://blogs.msdn.microsoft.com/benwilli/2015/09/10/tasks-are-still-not-threads-and-async-is-not-parallel/ - user585968

0

最简单的方法是允许用户将线程数量作为命令行参数输入。

int numberOfThreads = int.Parse(args[0]);

在这个例子中,我使用Enum.Range生成一个具有正确元素数量的IEnumerable,然后使用LINQ启动任务。
static void Main(string[] args)
{
    int numberOfThreads = int.Parse(args[0]);
    Task.WaitAll(
        Enum.Range(0, numberOfThreads)
            .Select(
                Task.Factory.StartNew(() => doStuff())
            )
            .ToArray()
        )
    );
    Console.WriteLine("Done !");
}

如果您确实需要那些任务,也可以使用{{link1:Parallel.For}}。

static void Main(string[] args)
{
    int numberOfThreads = int.Parse(args[0]);

    Parallel.For(1, numberOfThreads, (i) => doStuff());
    Console.WriteLine("Done !");
}

如果您需要更多的迭代次数,但想限制线程数量,可以使用ParallelOptions。在这个例子中,我允许100次迭代,但只使用用户指定的线程数。
static void Main(string[] args)
{
    int numberOfThreads = int.Parse(args[0]);

    Parallel.For(
        1, 
        100, 
        new ParallelOptions
        {
            MaxDegreeOfParallelism = numberOfThreads
        },
        (i) => doStuff()
    );
    Console.WriteLine("Done !");
}

非常感谢,我的程序需要读取文本文件的每一行,并为每一行启动一个线程。假设文本文件包含100行,那么线程会继续创建,直到程序执行完所有行的任务才停止,或者如果用户选择10个线程,它只会读取前10行吗?谢谢。 - Stéphanie Autire
Enumerable.Range() 返回 IEnumerable<int>。 - Sean B

-1
也许你应该使用一个长度为用户所需的数组,并使用Task.Factory.StartNew()初始化数组的每个元素?希望这能有所帮助^^

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接