嗨,我有一个使用一个线程将缓冲区从*src
复制到*dst
的应用程序,但是我想让线程在程序的开头启动。当我想使用线程时,我想将*src
,*dst
和size
传递给线程,以便它可以开始复制缓冲区。我该如何实现?因为当我启动线程时,我在实例化对象时传递了值,即创建线程时的ThreadX
。
Thread^ t0 = gcnew Thread(gcnew ThreadStart(gcnew ThreadX(output, input, size), &ThreadX::ThreadEntryPoint));
总而言之,我想这样做:
示例代码如下所示。
谢谢!
#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
}
答案 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,并在线程不工作时让它坐在阻塞操作中。