0

问题很简单,但解决方案让我望而却步。我想调用两个函数并让它们同时运行(在单独的线程中),但我只能在之后void function1()调用和void function2()运行,而不是在期间运行。我为处理器 1 和 2 设置了线程关联(我有一个多核处理器,希望你也有一个)。

我看到一次只调用一个函数的方式仅仅是因为我得到了 only 的输出,function 1而通常我会看到function 1and的混合function 2

随意重新调整代码以使其工作,但请尽量保持原始方法与类中线程调用函数的方式保持不变。这是完整的代码。

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <iostream>

class thread_class
{
    private:


    public:

    void function1()
    {
        for(int count = 0; count < 1000; count++)
            std::cout<<"function 1"<<std::endl;
    }
    void function2()
    {
        for(int count = 0; count < 1000; count++)
            std::cout<<"function 2"<<std::endl;
    }
    thread_class(){}
    ~thread_class(){}
    DWORD_PTR WINAPI threadMain0()
    {
        function1();

        return 0;
    }
    DWORD_PTR WINAPI threadMain1()
    {
        function2();

        return 0;
    }
    void thread()
    {
        HANDLE *m_threads = NULL;
        DWORD_PTR c = 2;

        m_threads = new HANDLE[c];

        DWORD_PTR i = 0;
        DWORD_PTR m_id0 = 0;
        DWORD_PTR m_mask0 = 1 << i;

        m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain0(), (LPVOID)i, NULL, &m_id0);
        SetThreadAffinityMask(m_threads[i], m_mask0);

        wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask0);

        i = 1;
        DWORD_PTR m_id1 = 0;
        DWORD_PTR m_mask1 = 1 << i;

        m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain1(), (LPVOID)i, NULL, &m_id1);
        SetThreadAffinityMask(m_threads[i], m_mask1);

        wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask1);
    }
};
int main()
{
    thread_class* MAIN_THREADS;

    MAIN_THREADS = new thread_class();

    MAIN_THREADS->thread();

    delete MAIN_THREADS;

    return 0;
}

编辑:这是下面代码的略微修改版本,显示它没有并行运行。

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <iostream>

class thread_class
{
    private:


    public:

    void function1()
    {
        int exit = 0;

        while(exit == 0)
        {
            std::cout<<"enter 1 to exit:"<<std::endl;
            std::cin>>exit;
        };
    }
    void function2()
    {
        for(int count = 0; count < 1000; count++)
            std::cout<<"function 2"<<std::endl;
    }
    thread_class(){}
    ~thread_class(){}
    DWORD_PTR WINAPI threadMain0()
    {
        function1();

        return 0;
    }
    DWORD_PTR WINAPI threadMain1()
    {
        function2();

        return 0;
    }
    void thread()
    {
        HANDLE *m_threads = NULL;
        DWORD_PTR c = 2;

        m_threads = new HANDLE[c];

        DWORD_PTR i = 0;
        DWORD_PTR m_id0 = 0;
        DWORD_PTR m_mask0 = 1 << i;

        m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain0(), (LPVOID)i, NULL, &m_id0);
        SetThreadAffinityMask(m_threads[i], m_mask0);

        wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask0);

        i = 1;
        DWORD_PTR m_id1 = 0;
        DWORD_PTR m_mask1 = 1 << i;

        m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain1(), (LPVOID)i, NULL, &m_id1);
        SetThreadAffinityMask(m_threads[i], m_mask1);

        wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask1);
    }
};
int main()
{
    thread_class* MAIN_THREADS;

    MAIN_THREADS = new thread_class();

    MAIN_THREADS->thread();

    delete MAIN_THREADS;

    return 0;
}
4

2 回答 2

2

所以,有几点:

1) 不能将常规成员函数用作 ThreadProc。如果你必须强制转换它才能编译它可能是错误的。ThreadProc 函数需要是自由的或静态的。他们也有错误的签名,因为 ThreadProc 需要一个 void* 参数。

2) 当你真的需要 DWORD 时,有几个地方可以使用 DWORD_PTR,例如来自 ThreadProc 的返回值ci、 等。

3)从CreateProcess文档:

A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multithreaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.

有机会写入cout最终命中 CRT。它可能没有,即使有,你也可能没有问题,但如果你这样做了,那是个不错的地方。

4) I/O 根本不保证是交错的,因此写入cout不是确定线程是否同时运行的好方法。我已经添加了一些Sleep对线程的调用,并且最初也将它们创建为挂起,因此我可以将它们尽可能靠近地启动,以使 I/O 看起来像是交错的,但这可能只是巧合。一旦我确实看到您可能会发现,当线程启动时,打印的字符串并endl没有相互连接,也就是说,我看到两个字符串后跟两个线端。在那之后它有点交错。

5) 在从线程下删除类之前,您总是希望等待线程退出。您通常还希望在完成后关闭它们的句柄。

我消除了构造函数/析构函数,因为它们是空的和其他绒毛,只是为了保持尽可能短。

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <iostream>

class thread_class
{
    public:
    void function1()
    {
        Sleep(0);
        for(int count = 0; count < 10; count++)
        {
            std::cout<<"function 1"<<std::endl;
            Sleep(0);
        }
    }
    void function2()
    {
        Sleep(0);
        for(int count = 0; count < 10; count++)
        {
            std::cout<<"function 2"<<std::endl;
            Sleep(0);
        }
    }
    static DWORD WINAPI threadMain0(LPVOID param)
    {
        thread_class* This = static_cast<thread_class*>(param);
        This->function1();
        return 0;
    }
    static DWORD WINAPI threadMain1(LPVOID param)
    {
        thread_class* This = static_cast<thread_class*>(param);
        This->function2();
        return 0;
    }
    void thread()
    {
        HANDLE m_threads[2] = {};
        DWORD threadIDs[2] = {};
        LPTHREAD_START_ROUTINE threadProcs[2] = {threadMain0, threadMain1};
        DWORD_PTR mask = 0;
        for(int i = 0; i < 2; ++i)
        {
            m_threads[i] = CreateThread(NULL, 0, threadProcs[i], this, CREATE_SUSPENDED, &threadIDs[i]);
            mask = 1 << i;
            SetThreadAffinityMask(m_threads[i], mask);
            wprintf(L"Creating Thread %d (0x%08p) Assigning to CPU 0x%08p\r\n", i, m_threads[i], mask);
        }
        for(int i = 0; i < 2; ++i)
        {
            ResumeThread(m_threads[i]);
        }
        WaitForMultipleObjects(2, m_threads, TRUE, INFINITE);
        for(int i = 0; i < 2; ++i)
        {
            CloseHandle(m_threads[i]);
        }
    }
};

int main()
{
    thread_class* MAIN_THREADS;
    MAIN_THREADS = new thread_class();
    MAIN_THREADS->thread();
    delete MAIN_THREADS;
    return 0;
}
于 2013-09-21T12:34:39.513 回答
1

我在您的代码的两个版本中看到的问题之一是 NULL 传递给 CreateThread() 函数的 dwCreationFlags 参数。这意味着创建的线程将在 CreateThread() 退出后立即启动(如果您配备了多核 CPU 和幸运调度,则甚至更快)。因此,您的第一个线程似乎在第二个线程有机会诞生之前完成了他的工作(因为线程创建在时间方面是昂贵的操作 - 数十或数百毫秒)。

那么您可以尝试以下方法:

  1. 使用 CREATE_SUSPENDED 标志而不是 NULL 创建两个线程
  2. 然后向两个线程调用 ResumeThread
  3. 使函数执行时间更长(可能是数百万次迭代)
于 2013-09-21T11:50:13.480 回答