我在使用python的过程当中发现了这个有这样的错误,后来看了下面这篇文档才知道原因所在。
最近在编写一个局域网的聊天工具,在编写客户端时,我把界面部分和事件处理函数写好后,准备再开一个线程用于接收服务器端发来的数据报,根据数据报的类型来调用相应的子模块。我用的是gtk+写的界面,由于两个线程都涉及到界面的问题,并且我并没有考虑同步的问题,所以导致了标题中所说的问题。
我的数据接收模块(单独的一个线程)的大致内容如下:
while ( RecvInfo(datagram, &size_datagram) ){
/* 提取报文头 */
struct ConnProto *ptr = (struct ConnProto *)pData;
pconn = *ptr;
if (pconn.type == 0) {
// 当前登录成功,下载用户列表
}else if (pconn.type == -1) {
// 当前用户已登录,先下线
gchar str[100] = "系统提示:[当前用户已登录,请先下线]";
message_box(str, GTK_MESSAGE_ERROR);
}else if (pconn.type == -2) {
// 当前用户不存在,先注册
}else if (pconn.type == -3) {
// 当前用户密码错误
}else if (pconn.type == 10) {
// 有新用户上线
}else if (pconn.type == 11) {
// 注册成功
}else if (pconn.type == -11) {
// 当前用户已存在
}else if (pconn.type ==2) {
// 私聊处理
}else if (pconn.type == 3) {
// 群聊处理
}else if (pconn.type == 4) {
// 退出处理
}else {
// 其他处理
gchar str[100] = "系统提示:[当前有不识别的命令]";
message_box(str, GTK_MESSAGE_ERROR);
}
}
其中,message_box ()函数涉及到界面的问题,就是一个消息框的界面。刚开始的时候,while循环中没有放置sleep()函数(你可能会有疑问为什么放置这个函数,其实我的接收数据的函数RecvInfo () 函数还没有写,我只是用一个空函数代替,所以如果不放置sleep ()的话,循环速度就会太快),出现的问题如下:
chat: Fatal IO error 11 (资源暂时不可用) on X server :0.0.
当在 while ()循环中加入 sleep (2)时,出现的问题如下:
The program 'chat' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadIDChoice (invalid resource ID chosen for this connection)'.
(Details: serial 761 error_code 14 request_code 144 minor_code 2)
(Note to programmers: normally, X errors are reported asynchronously;
that is, you will receive the error a while after causing it.
To debug your program, run it with the --sync command line
option to change this behavior. You can then get a meaningful
backtrace from your debugger if you break on the gdk_x_error() function.)
在网上搜了一下,说是由于两个线程抢占GUI资源导致的,去除其中一个线程中的控件句柄,说白了就是只能有一个线程来画界面。
实际上,在gtk+程序中使用线程的话,不能直接使用 linux 中的 pthread 了,而应该用 gtk+ 中提供的线程函数。关于 gtk+ 中使用多线程的方法,详见另一篇文章。