我正在编写一个多线程Qt应用程序,但是由于与OpenGL相关的调用,部分代码必须始终在主线程中执行。
模拟问题的粗糙代码将是:
QMutex mutex;
void openGLCalls()
{
}
void foo1()
{
mutex.lock();
openGLCalls();
mutex.unlock();
}
class CBHandler : public QObject
{
public:
CBHandler(QObject *parent = NULL)
{
connect(this, SIGNAL(requestCallbackExec()), SLOT(runCallback()), Qt::BlockingQueuedConnection);
}
static CBHandler *Instance();
public slots:
void runCallback ()
{
//in the main thread as object lies there
openGLCalls();
}
signals:
void requestCallbackExec ();
};
class Thread1
{
void run()
{
while(1)
{
mutex.lock();
CBHandler::Instance()->emit requestCallbackExec();
mutex.unlock();
}
}
};
void main()
{
Thread1 thread;
CBHandler cbhandler;
thread.start();
while(1)
{
if(/*some key pressed*/)
{
foo1();
}
}
}
以上代码确保“ openGLCalls()”始终在主线程中执行。 但是问题是,如果互斥锁被Thread1锁定,并且主线程尝试调用foo1,那么当试图锁定互斥锁时,主线程会进入休眠状态。 而且由于主线程处于休眠状态,因此线程1锁定的互斥锁永远不会因未请求“ requestCallbackExec”信号而被解锁。
答案 0 :(得分:0)
您应该在sudo apt install flex-old
等待时让事件循环旋转。似乎没有办法做到这一点。这样您就可以忙着等待:
Queue
您可以在public static void DoSomething(int x)
{
Console.WriteLine("Starting " + x);
Thread.Sleep((x%10) * 1000);
}
public static void Main(string[] args)
{
Queue<int> myList = new Queue<int>();
for (int i = 0; i < 100; i++)
myList.Enqueue(i);
// This would be random if we'd use a List
//Parallel.ForEach(myList, new ParallelOptions() { MaxDegreeOfParallelism = 4 }, x => DoSomething(x));
// This will get the right order. But 2 can still be faster than 1 if 2's thread is quicker. But generally you got your order.
Parallel.For(
0, // We count from 0
myList.Count, // to max entries..
new ParallelOptions() { MaxDegreeOfParallelism = 4 }, // don't forget this one ;)
(x) => { lock (myList) { int y = myList.Dequeue(); Console.WriteLine(y); DoSomething(y); } });
}
调用中添加超时以不使CPU过热,但这会花费一些延迟。