我不是计算机科学背景的。请为我指出以下正确的资源。这是我在 C++/CLI 中使用 Windows 窗体所做的事情。
private: System::Void button4_Click(System::Object^ sender, System::EventArgs^ e)
{
for (i=0; i < n ;i++){
array<UInt32>^ Buffer = gcnew array<UInt32>(numericTextBox2->IntValue);
/* Some time consuming process. Takes approximately 8 to 10 seconds
and fills Buffer.*/
Thread^ executerThread = gcnew Thread(gcnew ParameterizedThreadStart(this, &Form1::Task));
executerThread.Start((Object^)Buffer)
}
}
private: void Task(Object^ i)
{
array<UInt32>^ Buffer = (array<UInt32>^)i;
mut->WaitOne();
/* Here I send the Buffer as a stream of integers through the hardware driver.
This stream is sent out by the hardware(with built in internal clock) at
a fixed frequency of one integer every micro second. */
mut->ReleaseMutex();
return
}
我需要所有线程按照它们启动的顺序运行 Task() 函数,就像在循环内调用函数 Task() 一样。如果我的缓冲区非常小,我想我会遇到同步问题。如果我的数组非常大并且准备它们所花费的时间大于执行任务的时间,则该程序符合我的目的,因为线程在调用它们时按顺序执行 Task()。在这种情况下,最多有两个线程(一个运行程序,另一个等待资源)。但是如果我的数组很短,Task执行时间很长(不确定,因为这涉及到硬件驱动),那么就是有多个线程在等待资源。我不知道任务是否按照它们启动的顺序执行。我认为由操作系统根据其规则执行这些操作。所以我需要一种方法或方式让这些线程按照它们启动的顺序执行。
非常感谢。
最佳答案
我认为解决这个问题的最简单方法是使用 future 队列。在 UI 端,启动一个异步任务来填充每个缓冲区。然后,启动一个最终的异步任务来等待结果并将它们传递给驱动程序。类似于以下内容:
private: System::Void button4_Click(System::Object^ sender, System::EventArgs^ e)
{
std::queue<std::future<std::vector<uint32_t>>> items;
for (i=0; i < n ;i++){
items.push(std::async(std::launch::async, [i] { return CreateBuffer(i); });
}
complete_ = std::async(
std::launch::async,
[items_ = std::move(items)]
{
while (!items_.empty())
{
SendBufferToDriver(items_.front().get());
items_.pop();
}
});
}
这将并行预处理所有数组,然后将它们按顺序发送给驱动程序。由于一切都是异步完成的,这也将避免在处理过程中阻塞您的 UI 线程。
并发症:
请记住,这只是一个草图。如果用户在所有数据发送到驱动程序之前关闭窗口,您还必须考虑如何取消/终止此过程。如果这是一个持续的过程,用户可以多次单击按钮以随着时间的推移添加更多数据,那么解决方案会稍微复杂一些。基本思想是相同的,但您可能需要一个 bounded buffer
而不是一个简单的队列,它将不得不移出功能范围。
没有 std::future 吗?
如果您坚持使用不支持 C++11 的旧编译器,您可以使用 System.Threading.Tasks.Task<T>
完成同样的事情。 .界面类似于std::async
/std::future
.
关于c++ - 如何创建一系列线程以按启动顺序执行任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52921974/