现在有多个树控件,每个树控件显示的本地某个目录下的所有文件。
在显示每个节点状态的时候,需要向服务器请求该节点的属性,然后根据不同的属性显示不同的图标状态。(有点像SVN的状态同步)
网络请求只能有一个线程,所以我设计了一个队列,把要请求状态的子节点依次排入队列。
每次子节点向服务器请求完毕后删除出队列,并根据返回的属性,设置树节点的状态。
现在的问题如下:
1.队列中某个树节点在向服务器请求状态后,如果这个节点被删除了,则修改节点状态时该节点Handle已经无效,会导致崩溃。而请求线程并不知道树控件发生了什么。如何解决?
2.客户端关闭时,如果队列中仍有节点需要同步,这个时候如何设计“等待”的机制,让队列处理完同步再安全退出呢?
我在设计的时候,请求线程访问树控件会导致代码死锁,百思不得其解如果有描述不清楚的地方请大家指出。
望有经验的前辈指点
在显示每个节点状态的时候,需要向服务器请求该节点的属性,然后根据不同的属性显示不同的图标状态。(有点像SVN的状态同步)
网络请求只能有一个线程,所以我设计了一个队列,把要请求状态的子节点依次排入队列。
每次子节点向服务器请求完毕后删除出队列,并根据返回的属性,设置树节点的状态。
现在的问题如下:
1.队列中某个树节点在向服务器请求状态后,如果这个节点被删除了,则修改节点状态时该节点Handle已经无效,会导致崩溃。而请求线程并不知道树控件发生了什么。如何解决?
2.客户端关闭时,如果队列中仍有节点需要同步,这个时候如何设计“等待”的机制,让队列处理完同步再安全退出呢?
我在设计的时候,请求线程访问树控件会导致代码死锁,百思不得其解如果有描述不清楚的地方请大家指出。
望有经验的前辈指点
2、更新控件数据最终是通过SendMessage给控件发消息来实现的,当目标控件不属于当前线程时,SendMessage会等待控件所属线程来处理消息,消息处理完后才会返回。在你的程序中,工作线程给主线程的控件SendMessage,等待主线程处理;而主线程在等待工作线程结束,没有处理消息,工作线程会一直停在SendMessage里面,所以死锁。可以改成关闭程序时通过定时检查工作线程是否已结束,然后再退出主线程。
分享思路如下:
zxdyu2009说的很对,线程只管请求数据与接收数据,数据接收后处理不在线程里,而是由相应的处理逻辑去处理。
cnzdgs说的关闭程序时通过定时检查工作线程是否已结束,然后再退出主线程是很正确。但关键在于等待过程中不能让小西队列阻塞,因此在轮询时必须处理消息,解决思路如下:
while (TRUE == CSynchronizeSvn::Single().GetBusyState())
{
// Process all process messages
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
这样用户不会有卡的感觉。
另外,在树需要重建(这时候树的所有节点都将被删除)的时候,需要通过禁用UI的方式阻止用户重复push刷新任务,这样就不会出现刷新了不存在的节点的问题。