65.9K
CodeProject 正在变化。 阅读更多。
Home

简单的辅助线程

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2016年3月15日

CPOL
viewsIcon

40952

downloadIcon

982

辅助线程为您提供并行处理能力

引言

有时,我们需要一个额外的线程来并行执行任务,或者只是为了解除主线程的阻塞。为了获得更好的性能,我们不希望每次都创建一个新线程。此外,我们需要对线程进行更多的控制。 在本文中,我们将实现一个具有以下功能的线程。

  • 您无需定义线程过程,而是可以使用 lambda 提交任何函数
  • 完全用 C++11 实现,兼容任何操作系统
  • 提交一个异步执行的任务
  • 提交一个同步执行的任务(但在工作线程上)
  • 自动等待任务完成
  • 实现大量使用 C++ 11(线程、lambda、条件变量)

Using the Code

下面的示例代码列出了工作线程的用法

#include <iostream>
#include <chrono>
#include <thread>
#include "workerthread.h"

int main()
{
    std::cout << "Hi, Welcome to demo of worker thread" << std::endl;

    {
        // Create two worker threads
        WorkerThread thread;
        WorkerThread thread2;

        // Example of a synchronous task
        thread.doSync([]{    std::cout << "First - blocking call" << std::endl;    });

        for (int i = 1; i < 100; i++)
        {
            auto& t = i % 2 == 0 ? thread : thread2;
            if (i == 10) // Another synchronous task in between
            {
                thread.doSync([]{    
                std::cout << "Second - blocking call" << std::endl;    });
            }
            // Multiple asynchronous tasks queued
            t.doAsync([i]
            {
                std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(200));
                std::cout << (i % 2 == 0 ? "thread-" : "thread2-") 
                << "iteration number: " << i << std::endl;
            });
        }
    
        thread.doSync([]{    std::cout << "Last - blocking call";    });
    }// Added extra scope to demo destruction of worker thread
    std::cout << "This must be last line\n";

}

工作线程的实现

  • 使用 C++ 函数构造来存储提交的任务
  • 完成当前队列并等待新工作的信号
void WorkerThread::startThread()
{
    std::unique_lock<std::mutex> l(mutex);
    do
    {
        while (isRunning && tasks.empty())
            itemInQueue.wait(l);

        while (!tasks.empty())
        {
            auto size = tasks.size();
            printf("Number of pending task are %d\n", size);
            const std::function<void()> t = tasks.front();
            tasks.pop_front();
            l.unlock();
            t();
            l.lock();
        }
        itemInQueue.notify_all();

    } while (isRunning);
    itemInQueue.notify_all();
}

异步任务只是被排队,调用线程不会被阻塞

void WorkerThread::doAsync(const std::function<void()>& t)
{
    std::lock_guard<std::mutex> _(mutex);
    tasks.push_back(t);
    itemInQueue.notify_one();
}

同步任务稍微复杂一些,我们需要阻塞调用线程,直到在提交的任务之前的所有任务都已排队并且提交的任务完成。

void WorkerThread::doSync(const std::function<void()>& t)
{
    std::condition_variable event;
    bool finished = false;

    std::unique_lock<std::mutex> l(mutex);
    auto lambda = [this, &t, &finished, &event]
    {
        t();
        std::lock_guard<std::mutex> l(mutex);

        finished = true;
        event.notify_one();
    };
    tasks.push_back(lambda);
    itemInQueue.notify_one();

    while (!finished)
        event.wait(l);
}

通过少量修改,此类可以用于采用基于优先级的任务。

© . All rights reserved.