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

问题描述 投票:0回答:2

嗨,我有一个应用程序,使用一个线程将缓冲区从*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
}
c++ .net multithreading thread-safety c++-cli
2个回答
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个队列来处理请求和响应,队列的每个元素都是输入和输出参数。


0
投票

不要暂停线程。这是糟糕的设计,很有可能会引发你的问题。

相反,可以这样想:让线程阻塞等待它应该做什么的信息。当它获得该信息时,它应该解锁,完成工作,然后再次阻止等待下一件事。

快速搜索“C#阻塞集合”揭示了BlockingCollection<T>类,并且这个guide取消了其中一个阻塞操作。使它在您的线程退出时激活CancellationToken,并让线程在阻塞操作不能正常工作时等待。

© www.soinside.com 2019 - 2024. All rights reserved.