基于程序描述的多线程推荐

2024-04-26

我想描述我的程序的一些细节,并获得有关最适用的最佳多线程模型的反馈。我现在花了很多时间阅读有关 ThreadPool、Threads、Producer/Consumer 等的内容,但尚未得出可靠的结论。

我有一个文件列表(格式相同)但内容不同。我必须对每个文件执行工作。这项工作包括读取文件、进行一些大约需要 1-2 分钟的直接数字运算的处理,然后在最后写入大型输出文件。

我希望 UI 界面在我启动指定文件的工作后仍然能够响应。

一些问题:

  1. 我应该使用什么模型/机制?生产者/消费者、工作池等
  2. 我是否应该在 UI 中使用 BackgroundWorker 来实现响应能力,或者只要我保留 UI 线程以继续响应用户输入,我就可以从表单内启动线程吗?
  3. 我如何获取每个文件上每个单独工作的结果或状态,并以线程安全的方式将其报告给 UI,以便随着工作的进展向用户提供反馈(可能有近 1000 个文件需要处理)

Update:

到目前为止反馈很好,非常有帮助。我正在添加以下询问的更多详细信息:

  • 输出到多个独立文件。每个“工作项”一组输出文件,然后在“工作项”完成之前由另一个进程读取和处理这些输出文件

  • 工作项/线程不共享任何资源。

  • 工作项部分使用利用 boost 库的非托管静态库进行处理。


根据评论更新:
我不同意线程池无法处理您遇到的工作负载的说法......让我们看看您的问题并更具体:
1. 您有近 1000 个文件。
2. 每个文件可能需要长达 2 分钟的 CPU 密集型工作来处理。
3. 您希望通过并行处理来提高吞吐量。
4. 您希望在每个文件完成时发出信号并更新 UI。

实际上,您不想运行 1000 个线程,因为您受到拥有的核心数量的限制...并且由于它是 CPU 密集型工作,因此您可能会用很少的线程来最大化 CPU 负载(在我的程序中,它是通常每个核心有 2-4 个线程是最佳的)。

所以你不应该加载 1000 个工作项ThreadPool并期望看到吞吐量的增加。您必须创建一个始终以最佳数量的线程运行的环境,这需要一些工程设计。

我将不得不稍微反驳我最初的陈述,并实际上推荐生产者/消费者设计。看看这个question https://stackoverflow.com/questions/2294485/c-once-the-main-thread-sleep-all-thread-stopped/2295220#2295220有关图案的更多详细信息。

生产者可能如下所示:

class Producer
{
    private final CountDownLatch _latch;
    private final BlockingQueue _workQueue;
    Producer( CountDownLatch latch, BlockingQueue workQueue)
    {
        _latch = latch;
        _workQueue = workQueue;
    }

    public void Run()
    {
        while(hasMoreFiles)
        {
            // load the file and enqueue it
            _workQueue.Enqueue(nextFileJob);
        }

        _latch.Signal();
    }
}

这是你的消费者:

class Consumer
{
    private final CountDownLatch _latch;
    private final BlockingQueue _workQueue;

    Consumer(CountDownLatch latch, BlockingQueue workQueue, ReportStatusToUI reportDelegate)
    {
        _latch = latch;
        _workQueue = workQueue;
    }

    public void Run()
    {
        while(!terminationCondition)
        {
            // blocks until there is something in the queue
            WorkItem workItem = _workQueue.Dequeue();

            // Work that takes 1-2 minutes
            DoWork(workItem);

            // a delegate that is executed on the UI (use BeginInvoke on the UI)
            reportDelegate(someStatusIndicator);
        }

        _latch.Signal();
    }
}

A CountDownLatch:

public class CountDownLatch
{
    private int m_remain;
    private EventWaitHandle m_event;

    public CountDownLatch(int count)
    {
        Reset(count);
    }

    public void Reset(int count)
    {
        if (count < 0)
            throw new ArgumentOutOfRangeException();
        m_remain = count;
        m_event = new ManualResetEvent(false);
        if (m_remain == 0)
        {
            m_event.Set();
        }
    }

    public void Signal()
    {
        // The last thread to signal also sets the event.
        if (Interlocked.Decrement(ref m_remain) == 0)
            m_event.Set();
    }

    public void Wait()
    {
        m_event.WaitOne();
    }
}

Jicksa 的阻塞队列 http://jaksa76.blogspot.com/2009/03/blocking-queue-in-c.html:

class BlockingQueue<T> {
    private Queue<T> q = new Queue<T>();

    public void Enqueue(T element) {
        q.Enqueue(element);
        lock (q) {
            Monitor.Pulse(q);
        }
    }

    public T Dequeue() {
        lock(q) {
            while (q.Count == 0) {
                Monitor.Wait(q);
            }
            return q.Dequeue();
        }
    }
}

那么剩下什么呢?现在你所要做的就是启动所有线程......你可以在ThreadPool, as BackgroundWorker,或每一个作为new Thread 这没有什么区别.

您只需要创建一个Producer以及最佳数量Consumers考虑到您拥有的核心数量(每个核心大约 2-4 个消费者),这是可行的。

父线程(NOT你的 UI 线程)应该阻塞,直到所有消费者线程完成:

void StartThreads()
{
    CountDownLatch latch = new CountDownLatch(numConsumer+numProducer);
    BlockingQueue<T> workQueue = new BlockingQueue<T>();

    Producer producer = new Producer(latch, workQueue);
    if(youLikeThreads)
    {
        Thread p = new Thread(producer.Run);
        p.IsBackground = true;
        p.Start();
    }
    else if(youLikeThreadPools)
    {
        ThreadPool.QueueUserWorkItem(producer.Run);
    }

    for (int i; i < numConsumers; ++i)
    {
        Consumer consumer = new Consumer(latch, workQueue, theDelegate);

        if(youLikeThreads)
        {
            Thread c = new Thread(consumer.Run);

            c.IsBackground = true;

            c.Start();
        }
        else if(youLikeThreadPools)
        {
            ThreadPool.QueueUserWorkItem(consumer.Run);
        }
    }

    // wait for all the threads to signal
    latch.Wait();

    SayHelloToTheUI();
}

请注意,上述代码仅供说明之用。您仍然需要向ConsumerProducer并且您需要以线程安全的方式执行此操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于程序描述的多线程推荐 的相关文章

随机推荐

  • 此 xpath 查询的 Flex/AS3/E4X 等效项是什么?

    鉴于此文档
  • 一个应用程序的最大线程数?

    我想知道一个应用程序的最大线程数 您知道 Thread activeCount 返回正在运行的线程组及其子组中的活动线程数 如果我知道当前活动中要创建的最大线程数 我就可以限制活动线程 我正在使用线程进行 http 连接并捕获 Http 响
  • 类通过回调提供数据

    在用 C 编程一段时间后 我最近回到了 Visual C 因为 C 中的回调要容易得多 我有一个控制 0 连接设备的单例类 我的想法是在此类中创建一个函数 它将迭代一组 连接的设备并通过回调将其发布到任何可能需要它的地方 e g Singl
  • C++ 或 Java 中保存 20 位整数的数据类型

    Java 或 C 中是否有可以保存 20 位或更多数字的整数值的数据类型 long long 数据类型最多只能容纳 18 位数字 Java具体 您正在寻找BigInteger http docs oracle com javase 7 do
  • 如何在H2中定义Oracle Package procedure进行测试

    我正在测试一个 Spring Boot 应用程序 该应用程序将数据读取 写入 Oracle DB 该 Oracle DB 具有 Oracle 包以及这些包中的过程 在某些时候 Spring Boot应用程序通过实体存储库调用此过程 如下所示
  • 模拟 with 语句中使用的类

    我有一堂课有一个 exit and enter 函数 以便我可以在 with 语句中使用它 例如 with ClassName as c c do something 我现在正在尝试编写一个单元测试来测试这一点 基本上 我想测试一下do s
  • 运行时静默更新应用程序

    我的应用程序最初将使用 Windows Installer 进行部署 我正在寻找的解决方案的主要特征包括 支持应用程序静默更新 运行 或自动重启 客户 易于维护和管理包装 过程 避免复杂的定制或 安装脚本 您对我如何实现这一目标有什么想法吗
  • 如何测试两个哈希值(密码)是否相似?

    当用户创建密码时 我对其进行哈希处理 包括盐 并将其保存在数据库中 现在 当用户想要更改他或她的密码时 我想测试新密码是否与旧密码太相似 我已经在不同的服务上看到过这种情况 尤其是网上银行 所以 我想我会使用similar text or
  • 更改 DataGridViewComboBoxColumn 单元格的背景颜色

    我创建了一个 DataGridView 对象 其中包含 DataGridViewComboBoxColumn 类型的列 以允许用户从下拉列表中选择值 例如 如果用户选择 高 我想对组合框的背面进行着色 但是 它不会为组合框着色 而只会为组合
  • 如何使用程序集绑定重定向来忽略修订号和内部版本号

    我有几个 C NET 应用程序 以及供它们访问数据库的 API 我想将 API 的所有版本放入数据库中 并让它们选择最高版本和内部版本号 但坚持使用它们构建时使用的主要版本号和次要版本号 基本上当我参考API时1 2 3 4我想要参考阅读1
  • 基于github仓库的本地仓库创建本地git仓库并保持更新

    我有一些基本的 git 知识 但我不知道如何实现这一点 我正在尝试克隆 github WordPress 入门主题下划线 https github com automattic s 这个想法是创建一个基本框架based 经过一些修改 在该存
  • 无法将 PHP 表单放入表格中

    我创建了一个工作正常的表单 但是当我将其放入表格中时 它总是认为该表单不完整 有没有办法可以将其放入表格中 这样看起来不错 而不会出现此问题 我的 HTML h2 class green Interested in making life
  • .Net Core Web Api 异步不重要吗?

    我一直在编写我的 Web Api 控制器方法async关键字并一直在使用async一直往下 我最近尝试创建一个方法同步来看看它会如何影响性能 并惊讶地发现它对任何其他 http 请求都没有阻塞影响 举个例子 Route Foo class
  • aws key 和 Secret 在 aws cli 上工作但在 jenkins 上不起作用

    我正在尝试运行 python 脚本 其中包含使用 boto3 sdk 访问 s3 的代码 我已经在我的 Windows 机器中创建了默认配置文件 aws cli 命令在窗口 cmd 中可以正常工作以访问 s3 存储桶 python 脚本在窗
  • PHP 计算 JSON 请求中返回的项目数?

    我正在寻找一种方法来计算在搜索数据库时得到的这些 JSON 字符串中返回的项目数 以 PHP 表示 请原谅我 因为我对这一切一无所知 有人告诉我 因为 JSON 版本中没有返回计数 就像此数据库中的 XML 版本一样 我必须使用循环来计算结
  • 简单的http服务器

    好吧 这可能是一个愚蠢的问题 但关于节点 我已经尽我所能了 我设置了一个服务器 使用我们可以在任何节点演示或教程中找到的代码 var http require http var server http createServer functi
  • 如何在VueJS中将所有事件传递给父级

    传递道具 In VueJS如果你设置inheritAttrs to false并使用v bind attrs 您将组件中未声明的所有 props 传递给其子组件 是否有类似的方法将来自子级的所有事件传递给其父级VueJS 代码示例 Wrap
  • 无法加载 Spring ApplicationContext

    我正在为一个有点复杂的 spring 应用程序编写单元测试 我想加载 spring 上下文以便使用定义的 bean 我的 context xml 位于 src main resources context xml Maven 构建后 con
  • Keras模型拟合多项式

    我从四次多项式生成了一些数据 并希望在 Keras 中创建一个回归模型来拟合该多项式 问题是拟合后的预测似乎基本上是线性的 由于这是我第一次使用神经网络 我认为我犯了一个非常微不足道且愚蠢的错误 这是我的代码 model Sequentia
  • 基于程序描述的多线程推荐

    我想描述我的程序的一些细节 并获得有关最适用的最佳多线程模型的反馈 我现在花了很多时间阅读有关 ThreadPool Threads Producer Consumer 等的内容 但尚未得出可靠的结论 我有一个文件列表 格式相同 但内容不同