如何将参数传递给已经开始运行的线程

时间:2018-08-31 19:13:32

标签: c++ .net multithreading thread-safety c++-cli

嗨,我有一个使用一个线程将缓冲区从*src复制到*dst的应用程序,但是我想让线程在程序的开头启动。当我想使用线程时,我想将*src*dstsize传递给线程,以便它可以开始复制缓冲区。我该如何实现?因为当我启动线程时,我在实例化对象时传递了值,即创建线程时的ThreadX

Thread^ t0 = gcnew Thread(gcnew ThreadStart(gcnew ThreadX(output, input, size), &ThreadX::ThreadEntryPoint));

总而言之,我想这样做:

  1. 程序启动
  2. 创建线程
  3. 在线程中等待
  4. 传递参​​数并唤醒线程以开始复制
  5. 一旦在线程中完成复制,然后让主线程知道它已完成
  6. 在程序结束之前加入线程

示例代码如下所示。

谢谢!

#include "stdafx.h"
#include <iostream>
#if 1

using namespace System;
using namespace System::Diagnostics;
using namespace System::Runtime::InteropServices;
using namespace System::Threading;

public ref class ThreadX
{
    unsigned short* destination;
    unsigned short* source;
    unsigned int num;

public:
    ThreadX(unsigned short* dstPtr, unsigned short* srcPtr, unsigned int size)
    {
        destination = dstPtr;
        source = srcPtr;
        num = size;
    }

    void ThreadEntryPoint()
    {
        memcpy(destination, source, sizeof(unsigned short)*num);
    }

};


int main()
{

    int size = 5056 * 2960 * 10; //iris 15 size
    unsigned short* input; //16bit
    unsigned short* output;
    Stopwatch^ sw = gcnew Stopwatch();

    input = new unsigned short[size];
    output = new unsigned short[size];

    //elapsed time for each test
    int sw0;
    int sw1;
    int sw2; 
    int sw3;

    //initialize input
    for (int i = 0; i < size; i++) { input[i] = i % 0xffff; }

    //initialize output
    for (int i = 0; i < size; i++) { output[i] = 0; }


    // TEST 1 //////////////////////////////////////////////////////////////////////
    for (int i = 0; i < size; i++) { output[i] = 0; }

    //-----------------------------------------------------------------------
    Thread^ t0 = gcnew Thread(gcnew ThreadStart(gcnew ThreadX(output, input, size), &ThreadX::ThreadEntryPoint));
    t0->Name = "t1";
    t0->Start();
    t0->Join();
    //-----------------------------------------------------------------------


    return 0
}

2 个答案:

答案 0 :(得分:1)

基本上,您需要一些基本的构造块来解决此问题(我假设您只想执行一次此复制操作。如果您有恒定的输入流,我们可以轻松地扩展该解决方案):

1)共享内存-用于交换控制信息。在这种情况下,它将是源缓冲区指针,目标缓冲区指针和大小(从主线程到工作线程)。完成工作后,您还希望某些数据结构(以简单的布尔标志开头)在相反的方向(从工作线程到主线程)共享信息。

2)条件变量-将信号从主线程发送到工作线程,并且方向相反。因此,您需要2个不同的条件变量。

3)像互斥锁这样的同步原语,用于保护共享内存(因为两个线程将同时访问它们)

鉴于这些构建基块,程序的伪代码将如下所示:

struct Control {
     void* src, *dest;
     int num_of_bytes = -1;
     bool isDone = false;
     conditional_var inputReceived;
     conditional_var copyDone;
     mutex m;
};

 void childThread() {
     m.lock();
     while (num_of_bytes == -1) {
         inputReceived.wait(m); // wait till you receive input.
     }
     // Input received. Make sure you set src and dest pointers, before setting num_of_bytes
     mempcy(dest, src, num_of_bytes);
     isDone = true; // mark work completion.
     copyDone.notify(); // notify the main thread of work completion.
     m.unlock();
}


void mainThread()
{
      // Create worker thread at start;
      thread_t thread = pthread_create(&childThread);

      // Do other stuff...
      //
      //

      // Input parameters received. Set control information, and notify the 
      //  workerthread.
      mutex.lock();
      src = input.src;
      dest = input.dest;
      num_of_bytes = input.num_of_bytes;

      inputReceived.notify(); // wake up worker thread.

      while (!isDone) { // Wait for copy to be over.
           copyDone.wait();
      }

      m.unlock();  // unlock the mutex.
      thread.join(); // wait for thread to join. If the thread has already ended before we execute thread join, it will return immediately.

}

如果要扩展此解决方案以处理输入流,我们可以使用2个队列进行请求和响应,队列的每个元素都是输入和输出参数。

答案 1 :(得分:0)

不要暂停线程。那是不好的设计,很可能会在以后引起您的问题。

相反,应这样考虑:让线程 block 等待有关其操作的信息。当它获取到该信息时,应取消阻止,执行工作,然后再次阻止以等待下一件事。

快速搜索“ C#阻止集合”将显示BlockingCollection<T>类,并使用此guide取消其中一个阻止操作。进行设置,以便在线程退出时激活CancellationToken,并在线程不工作时让它坐在阻塞操作中。