2011-03-07 95 views
0

我有一个具有GUI和TCP服务器的应用程序。 TCP服务器运行在不同的线程中,当它收到某个数据包时,它应该开始播放视频文件(来自MediaPlayer对象)。问题是,作为一个GUI组件,视频可能仅在主线程调用时才显示。我添加了一个监听器类的主类:另一个线程的监听器

Class RequestListener implements NBRequestListener{ /* NBRequestListener is the interface */ 
public void onRequestArrived(String request) { 
processRequest(request); /* This method will run the video */ 
} 

我在主线程创建的监听器,并设置为服务器中的监听器:

RequestListener listener = new RequestListener(); 
server.setRequestListener(listener); 

服务器的代码是:

public void setRequestListener(_listener) { 
listener = _listener; } /* listener is defined as RequestListener */ 

和事件的调用(在服务器)仅仅是:

listener.onRequestArrived(input_from_client); 

但是侦听器方法在服务器线程中调用,而不是在主线程中调用,因此我得到异常:java.lang.reflect.InvocationTargetException。你能帮忙指出问题吗?

回答

1

多种方式来解决这一个,这里有二:

  1. 在活动中使用一个处理程序。例如,当您从后台线程收到通知,需要播放视频时,您会向您的活动处理程序发送消息。您的自定义处理程序中的代码可以在UI线程上运行。这里有一个教程(来自众多)http://www.helloandroid.com/taxonomy/term/43

  2. 当后台线程获取数据包时,在上下文类中广播一个Intent(startBroadcast())。在您的活动中为此广播注册接收者。

0

通常的方法是让消费者线程(这里是您的主线程)等待信号量或锁,并且生产者线程(这里是服务器线程)在资源可用时释放信号量或锁(即,当来自客户端的输入已被接收到时)。

查看java.util.concurrentjava.util.concurrent.locks包中的Lock和Semaphore。

+0

感谢,但由于我的主线程是GUI线程,它不会导致没有GUI组件出现(因为线程被锁定)? – MByD 2011-03-07 08:42:18

0

许多用户界面只需要一个线程(“事件”线程)在UI状态上执行操作。这是为了防止并发和一致性问题。

当您从另一个线程调用某个方法时,会破坏此规则。通常,一个好的解决方案是将事件添加到将在事件线程上下文中执行的事件队列中。

在摆动它是这样的:

SwingUtilities.invokeLater(new Runnable(){ 
    public void run(){ 
    //Your UI code to be run in the context of the event thread. 
    //In your case linking the video. 
    } 
}); 

正如你所说,你不应该阻止用户界面线程,否则将阻止它。