GTK多线程界面更新(续)

    上一篇《GTK多线程更新界面》中,我提到可以通过使用空闲函数来替代多线程处理GTK。随着对GTK的了解,发现这样并不是所有情况都合适。
    第一,如果使用空闲函数来处理socket程序,可能会造成数据接收不及时,特别是针对一些对数据及时性要求很高的程序。因为空闲函数只会在用户不对界面进行操作的时候(即系统空闲时)才进行。如果当前用户正在界面上执行某项耗时的操作,而此时有数据通过socket传送,那么该数据会等到用户的界面操作完成后才到达,造成了数据延时。那么应该怎么处理了,此时我们可以向GTK的主循环添加一个需要监视的socket描述符,然后让主循环对该socket进行扫描。这样做的效率在我看来是比使用空闲函数高的。具体使用方法:
        1.完成socket连接。
        2.使用g_io_channel_unix_new()生成一个全新的GChannel指针。注意:windows平台请使用g_io_channel_win32_new_socket()。
        3.通过g_io_add_watch()将刚才的GChannel指针添加到需要检测的队列中。
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>

#define ADDR "192.169.18.252"
#define PORT 5038

int new_message(GIOChannel *channel,GIOCondition condition,gpointer data);

int main()
{
	GMainLoop *loop;
	GIOChannel *channel;
	int sockfd;
	struct sockaddr_in addr;
	
	/*Create socket*/
	sockfd=socket(AF_INET,SOCK_STREAM,0);
	
	/*Init address*/
	memset(&addr,0,sizeof(addr));
	addr.sin_family=AF_INET;
	addr.sin_port=htons(PORT);
	addr.sin_addr.s_addr=inet_addr(ADDR);

	/*connect to the server*/
	if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr))==-1)
	{
		perror("connect");
		return 1;
	}
	
	/*Get channel from socket*/
	channel=g_io_channel_unix_new(sockfd);

	/*add the channel to main loop*/
	g_io_add_watch(channel,G_IO_IN|G_IO_HUP|G_IO_NVAL|G_IO_ERR,(GIOFunc)new_message,NULL);

	/*Enter the main loop*/
	loop=g_main_loop_new(NULL,FALSE);
	g_main_loop_run(loop);

	return 0;
}

int new_message(GIOChannel *channel,GIOCondition condition,gpointer data)
{
	if(condition==G_IO_IN)
	{
		/*Something to read*/
		char buffer[BUFSIZ];
		int sockfd;
	
		memset(buffer,0,sizeof(buffer));
		sockfd=g_io_channel_unix_get_fd(channel);
		recv(sockfd,buffer,BUFSIZ,0);
		g_print("%s",buffer);
		return TRUE;
	}
	else
	{
		/*Unable to read ,so remove the watch*/
		g_print("closed");
		return FALSE;
	}
}

    第二,在使用空闲函数时,如果空闲函数可能存在阻塞的情况,例如,连接超时。当空闲函数超时使,程序会一直阻塞,直到空闲函数完成。为了避免这种情况,必须使用多线程。如果直接按照网上的一些例子在线程中通过使用gdk_threads_enter()和gdk_threads_leave()来更新界面,这回导致程序移植问题(在我的测试中,linux系统上是不存在问题,但是如果使用mingw则界面会出现卡钝现象)。为了解决这个问题,我的建议是只在线程中处理数据(例如treeview的model数据等),在需要处理界面时,通过gdk_threads_idle_add()函数添加界面处理。这样就解决了程序的移植和后台更新数据等问题。

转载于:https://my.oschina.net/eatapple/blog/97180

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值