GTK多线程界面更新(续)
来源:互联网 发布:游戏优化器 编辑:程序博客网 时间:2024/04/30 22:51
原文地址:http://my.oschina.net/eatapple/blog/97180
上一篇《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指针添加到需要检测的队列中。
第二,在使用空闲函数时,如果空闲函数可能存在阻塞的情况,例如,连接超时。当空闲函数超时使,程序会一直阻塞,直到空闲函数完成。为了避免这种情况,必须使用多线程。如果直接按照网上的一些例子在线程中通过使用gdk_threads_enter()和gdk_threads_leave()来更新界面,这回导致程序移植问题(在我的测试中,linux系统上是不存在问题,但是如果使用mingw则界面会出现卡钝现象)。为了解决这个问题,我的建议是只在线程中处理数据(例如treeview的model数据等),在需要处理界面时,通过gdk_threads_idle_add()函数添加界面处理。这样就解决了程序的移植和后台更新数据等问题。
上一篇《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指针添加到需要检测的队列中。
01
#include <glib.h>
02
#include <stdio.h>
03
#include <string.h>
04
#include <stdlib.h>
05
#include <sys/socket.h>
06
#include <sys/types.h>
07
#include <arpa/inet.h>
08
09
#define ADDR "192.169.18.252"
10
#define PORT 5038
11
12
int
new_message(GIOChannel *channel,GIOCondition condition,gpointer data);
13
14
int
main()
15
{
16
GMainLoop *loop;
17
GIOChannel *channel;
18
int
sockfd;
19
struct
sockaddr_in addr;
20
21
/*Create socket*/
22
sockfd=socket(AF_INET,SOCK_STREAM,0);
23
24
/*Init address*/
25
memset
(&addr,0,
sizeof
(addr));
26
addr.sin_family=AF_INET;
27
addr.sin_port=htons(PORT);
28
addr.sin_addr.s_addr=inet_addr(ADDR);
29
30
/*connect to the server*/
31
if
(connect(sockfd,(
struct
sockaddr *)&addr,
sizeof
(addr))==-1)
32
{
33
perror
(
"connect"
);
34
return
1;
35
}
36
37
/*Get channel from socket*/
38
channel=g_io_channel_unix_new(sockfd);
39
40
/*add the channel to main loop*/
41
g_io_add_watch(channel,G_IO_IN|G_IO_HUP|G_IO_NVAL|G_IO_ERR,(GIOFunc)new_message,NULL);
42
43
/*Enter the main loop*/
44
loop=g_main_loop_new(NULL,FALSE);
45
g_main_loop_run(loop);
46
47
return
0;
48
}
49
50
int
new_message(GIOChannel *channel,GIOCondition condition,gpointer data)
51
{
52
if
(condition==G_IO_IN)
53
{
54
/*Something to read*/
55
char
buffer[BUFSIZ];
56
int
sockfd;
57
58
memset
(buffer,0,
sizeof
(buffer));
59
sockfd=g_io_channel_unix_get_fd(channel);
60
recv(sockfd,buffer,BUFSIZ,0);
61
g_print(
"%s"
,buffer);
62
return
TRUE;
63
}
64
else
65
{
66
/*Unable to read ,so remove the watch*/
67
g_print(
"closed"
);
68
return
FALSE;
69
}
70
}
第二,在使用空闲函数时,如果空闲函数可能存在阻塞的情况,例如,连接超时。当空闲函数超时使,程序会一直阻塞,直到空闲函数完成。为了避免这种情况,必须使用多线程。如果直接按照网上的一些例子在线程中通过使用gdk_threads_enter()和gdk_threads_leave()来更新界面,这回导致程序移植问题(在我的测试中,linux系统上是不存在问题,但是如果使用mingw则界面会出现卡钝现象)。为了解决这个问题,我的建议是只在线程中处理数据(例如treeview的model数据等),在需要处理界面时,通过gdk_threads_idle_add()函数添加界面处理。这样就解决了程序的移植和后台更新数据等问题。
- GTK多线程界面更新(续)
- gtk多线程更新界面
- 关于gtk多线程修改界面的问题
- gtk在多线程中的界面问题
- GTK+ 多线程
- 多线程耗时操作及界面更新
- 多线程之winform界面的更新
- Android多线程界面更新方法的总结
- Gtk线程刷新界面
- Gtk线程刷新界面
- GTK中使用多线程
- GTK 多线程例子
- Qt多线程操作界面---在QThread更新QProgressBar
- C#的Invoke和BeginInvoke、多线程中的界面更新
- WPF、WinForm(C#)多线程编程并更新界面(UI)
- Android多线程:Handler应用之更新UI界面
- WPF、WinForm(C#)多线程编程并更新界面(UI)
- 多线程异步处理:AsyncTask异步更新UI界面
- 关于点到直线距离的理解
- get请求方式中可能出现的乱码问题的解决方案
- gtk多线程更新界面
- Android APK反编译详解
- ubuntu win7双系统ubuntu挂载win7下分区方法
- GTK多线程界面更新(续)
- 图片压缩
- android 反编译工具
- iOS 消息推送 (待续)
- 内存管理FAQ(freshground )
- 【文本分类】 特征抽取之信息增益
- 在.cpp文件中,memset struct类型 所引发的segmentation fault
- 有关Dynamic Web TWAIN的一些问题
- c++基础---C++之模板