【问题标题】:Pthread Xlib programmingPthread Xlib 编程
【发布时间】:2012-04-15 07:18:38
【问题描述】:

我对 pthread 和 xlib 编程非常陌生。我试图以相反的方向绘制和移动两组矩形,但是当我运行我的代码时,我的问题只有一个线程被执行,而另一个被忽略。

我尝试了几个选项,但都无济于事。任何建议将不胜感激。

我已经包含了我的源代码。

谢谢。

编译:gcc -o Demofinal Demofinal.c -lpthread -lX11

运行:./Demofinal

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <pthread.h>
//Compile gcc -o Demofinal Demofinal.c -lpthread -lX11
//Run ./Demofinal

Display *dis;
Window win;
XEvent report;
GC green_gc;
XColor green_col;
Colormap colormap;
pthread_mutex_t mutexsum;

char green[] = "#00FF00";
void *createMoveLogs( void *ptr );
typedef struct str_thdata
{
int xval;
int yval;
int dir;
} thdata;

int main() {

pthread_t mvleft, mvright;
thdata data1, data2;        

/* initialize data to pass to thread 1 and 2*/
    data1.xval = 600;
    data1.yval = 115;
    data1.dir = 0;

    data2.xval = 5;
    data2.yval = 250;
    data2.dir = 1;



dis = XOpenDisplay(NULL);
win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 550, 550, 0, WhitePixel (dis, 0), WhitePixel(dis, 0));
XMapWindow(dis, win);
colormap = DefaultColormap(dis, 0);
green_gc = XCreateGC(dis, win, 0, 0);
XParseColor(dis, colormap, green, &green_col);
XAllocColor(dis, colormap, &green_col);
XSetForeground(dis, green_gc, green_col.pixel);

pthread_create( &mvleft, NULL, createMoveLogs, (void*) &data1);//thread 1 move right to left
pthread_create( &mvright, NULL, createMoveLogs, (void*) &data2);//thread 2 move left to right
pthread_join(mvleft, NULL);
pthread_join(mvright, NULL);    
return 0;
   }

  void *createMoveLogs( void *ptr )
  {
thdata *data;            
    data = (thdata *) ptr;

    int x= data->xval; int y = data->yval; int i;
int direction =  data->dir;
//check if the direction to move == left
if(direction == 0){
    pthread_mutex_lock(&mutexsum);
    for(i=0; i<=600; i++){
        XDrawRectangle(dis, win, green_gc, x, y, 145, 50);
        XDrawRectangle(dis, win, green_gc, x+200, y, 145, 50);
        XDrawRectangle(dis, win, green_gc, x+400, y, 145, 50);
        x-=10;
        if (x==-500){x=data->xval; i=0;}

        usleep(100000);
        XFlush(dis);
        XClearWindow(dis, win);
    } 
pthread_mutex_unlock(&mutexsum);
}else if(direction == 1){
    pthread_mutex_lock(&mutexsum);
    for(i=0; i<=600; i++){

        XDrawRectangle(dis, win, green_gc, x, y, 145, 50);
        XDrawRectangle(dis, win, green_gc, x-200, y, 145, 50);
        XDrawRectangle(dis, win, green_gc, x-400, y, 145, 50);
        x+=10;
        if (x==855){x=5; i=0;}
        usleep(100000);
        XFlush(dis);
        XClearWindow(dis, win);
    } 
    pthread_mutex_lock(&mutexsum);
  }
   }

【问题讨论】:

  • 一次只有一个线程可以进行 X11 调用
  • @BasileStarynkevitch 所以你的意思是我想要做的事情是不可能的?或者你有什么建议?
  • 确实,我建议只有一个线程执行 Xlib 调用。使用 GTK 或 QT 之类的工具包,只有主线程可以进行 GUI 调用。如果您绝对希望有多个线程执行 X11(这对我来说是错误的),请使用互斥锁进行序列化,并且不要忘记经常调用 Xsync。
  • @BasileStarynkevitch 好吧,我没有其他选择,这是我正在做的工作的要求,是的,感谢您的建议。不幸的是,我必须 X11 才能完成这项任务。

标签: c pthreads x11 xlib


【解决方案1】:

如果您对闪光灯敏感,请不要运行。

XInitThreads(); 
...

if(direction == 0){
    for(i=0; i<=600; i++){
        pthread_mutex_lock(&mutexsum);
        printf ("Thread %d\n", direction);
        XDrawRectangle(dis, win, green_gc, x, y, 145, 50);
        XDrawRectangle(dis, win, green_gc, x+200, y, 145, 50);
        XDrawRectangle(dis, win, green_gc, x+400, y, 145, 50);
        x-=10;
        if (x==-500){x=data->xval; i=0;}

        XFlush(dis);
        XClearWindow(dis, win);
        usleep(50000);
        pthread_mutex_unlock(&mutexsum);
        usleep(50000);
    }
}else if(direction == 1){
    for(i=0; i<=600; i++){
        pthread_mutex_lock(&mutexsum);
        printf ("Thread %d\n", direction);
        XDrawRectangle(dis, win, green_gc, x, y, 145, 50);
        XDrawRectangle(dis, win, green_gc, x-200, y, 145, 50);
        XDrawRectangle(dis, win, green_gc, x-400, y, 145, 50);
        x+=10;
        if (x==855){x=5; i=0;}
        XFlush(dis);
        XClearWindow(dis, win);
        usleep(50000);
        pthread_mutex_unlock(&mutexsum);
        usleep(50000);
    }
}

这会显示两组移动的矩形。当然这种方法是完全野蛮的,因为XClearWindow() 会导致不断的闪烁。在实际程序中,每个线程将负责清除旧框架中自己的部分,而不会触及其他部分。

【讨论】:

    【解决方案2】:

    Xlib 对来自多个线程的调用的支持仅在您调用 XInitThreads() 调用任何其他 Xlib 函数时才有效。即使这样,仍然存在一些错误,但没有它,就不会尝试在线程之间进行适当的锁定或同步。

    【讨论】:

      【解决方案3】:

      您有循环和usleep() 调用在互斥锁内部,这意味着第一个执行的线程将永远锁定另一个线程。

      【讨论】:

      • @geekosuar 那是我尝试做的最后一个。即使没有互斥体,它也保持不变。谢谢。
      • 如果没有互斥锁,您将很幸运没有得到核心转储,因为我在任何地方都看不到XInitThreads()。 Xlib 真的不是线程安全的。你最好不要尝试使用线程。
      猜你喜欢
      • 2011-10-01
      • 1970-01-01
      • 2013-09-17
      • 2013-03-14
      • 1970-01-01
      • 2011-03-17
      • 2021-03-21
      • 2012-06-22
      • 1970-01-01
      相关资源
      最近更新 更多