Beispiel #1
0
 def fn(self, *args):
     script = """
     new java.util.concurrent.Callable() {
         call: function() {
             return o.%s(%s);
         }
     };
     """ % (method, ",".join(["arg%d" % i for i in range(len(args))]))
     d = dict([("arg%d" % i, arg) for i, arg in enumerate(args)])
     d["o"] = self.o
     future = J.make_future_task(J.run_script(script, d))
     J.execute_future_in_main_thread(future)
     return fn_post_process(future.get())
Beispiel #2
0
 def fn(self, *args):
     script = """
     new java.lang.Runnable() {
         run: function() {
             o.%s(%s);
         }
     };
     """ % (method, ",".join(["arg%d" % i for i in range(len(args))]))
     d = dict([("arg%d" % i, arg) for i, arg in enumerate(args)])
     d["o"] = self.o
     future = J.make_future_task(J.run_script(script, d))
     J.execute_future_in_main_thread(future)
     return future.get()
Beispiel #3
0
 def fn(self, *args):
     script = """
     new java.util.concurrent.Callable() {
         call: function() {
             return o.%s(%s);
         }
     };
     """ % (method, ",".join(["arg%d" % i for i in range(len(args))]))
     d = dict([("arg%d" % i, arg) for i, arg in enumerate(args)])
     d["o"] = self.o
     future = J.make_future_task(J.run_script(script, d))
     J.execute_future_in_main_thread(future)
     return fn_post_process(future.get())
Beispiel #4
0
 def fn(self, *args):
     script = """
     new java.lang.Runnable() {
         run: function() {
             o.%s(%s);
         }
     };
     """ % (method, ",".join(["arg%d" % i for i in range(len(args))]))
     d = dict([("arg%d" % i, arg) for i, arg in enumerate(args)])
     d["o"] = self.o
     future = J.make_future_task(J.run_script(script, d))
     J.execute_future_in_main_thread(future)
     return future.get()
Beispiel #5
0
 def test_06_03_future_main(self):
     c = javabridge.run_script("""
     new java.util.concurrent.Callable() {
        call: function() { return 2+2; }};""")
     result = javabridge.execute_future_in_main_thread(
         javabridge.make_future_task(c, fn_post_process=javabridge.unwrap_javascript))
     self.assertEqual(result, 4)
def get_temp_current_image():
    '''Get the temporary ImagePlus object for the current thread'''
    script = """
    new java.util.concurrent.Callable() {
        call: function() {
            return Packages.ij.WindowManager.getTempCurrentImage();
        }
    };
    """
    gtci = J.make_future_task(J.run_script(script))
    imageplus_obj = J.execute_future_in_main_thread(gtci)
    return get_imageplus_wrapper(imageplus_obj)
def get_temp_current_image():
    '''Get the temporary ImagePlus object for the current thread'''
    script = """
    new java.util.concurrent.Callable() {
        call: function() {
            return Packages.ij.WindowManager.getTempCurrentImage();
        }
    };
    """
    gtci = javabridge.make_future_task(javabridge.run_script(script))
    imageplus_obj = javabridge.execute_future_in_main_thread(gtci)
    return imagej.imageplus.get_imageplus_wrapper(imageplus_obj)
Beispiel #8
0
 def createDisplay(self, name, dataset):
     '''Create a display that contains the given dataset'''
     #
     # Must be run on the gui thread
     #
     jcallable = J.run_script(
         """new java.util.concurrent.Callable() {
             call:function() {
                 return displayService.createDisplay(name, dataset);
             }
         };
         """, dict(displayService=self.o, name=name, dataset=dataset.o))
     future = J.make_future_task(jcallable,
                                 fn_post_process=wrap_display)
     return J.execute_future_in_main_thread(future)
Beispiel #9
0
 def createDisplay(self, name, dataset):
     '''Create a display that contains the given dataset'''
     #
     # Must be run on the gui thread
     #
     jcallable = J.run_script(
         """new java.util.concurrent.Callable() {
             call:function() {
                 return displayService.createDisplay(name, dataset);
             }
         };
         """, dict(displayService=self.o,
                   name = name,
                   dataset = dataset.o))
     future = J.make_future_task(jcallable,
                                 fn_post_process = wrap_display)
     return J.execute_future_in_main_thread(future)
def get_current_image():
    '''Get the WindowManager's current image
    
    returns a wrapped ImagePlus object
    '''
    #
    # Run this on the UI thread so its thread context is the same
    # as the macro invocation
    #
    script = """
    new java.util.concurrent.Callable() {
        call: function() {
            return Packages.ij.WindowManager.getCurrentImage();
        }
    };
    """
    gci = J.make_future_task(J.run_script(script))
    imageplus_obj = J.execute_future_in_main_thread(gci)
    return get_imageplus_wrapper(imageplus_obj)
def get_current_image():
    '''Get the WindowManager's current image
    
    returns a wrapped ImagePlus object
    '''
    #
    # Run this on the UI thread so its thread context is the same
    # as the macro invocation
    #
    script = """
    new java.util.concurrent.Callable() {
        call: function() {
            return Packages.ij.WindowManager.getCurrentImage();
        }
    };
    """
    gci = javabridge.make_future_task(javabridge.run_script(script))
    imageplus_obj = javabridge.execute_future_in_main_thread(gci)
    return imagej.imageplus.get_imageplus_wrapper(imageplus_obj)
Beispiel #12
0
def run_batch_macro(macro_text, imp):
    '''Run a macro in batch mode
    
    macro_text - the macro program to be run
    imp - an image plus to become the active image
    
    returns the image plus that was the active image at the end of the run
    '''
    script = """
    new java.util.concurrent.Callable() {
        call: function() {
             return interp.runBatchMacro(macro_text, imp);
        }
    };
    """
    interp = J.make_instance("ij/macro/Interpreter","()V");
    future = J.make_future_task(J.run_script(
        script, dict(interp=interp, macro_text=macro_text, imp=imp)))
    return J.execute_future_in_main_thread(future)
Beispiel #13
0
def run_batch_macro(macro_text, imp):
    '''Run a macro in batch mode
    
    macro_text - the macro program to be run
    imp - an image plus to become the active image
    
    returns the image plus that was the active image at the end of the run
    '''
    script = """
    new java.util.concurrent.Callable() {
        call: function() {
             return interp.runBatchMacro(macro_text, imp);
        }
    };
    """
    interp = javabridge.make_instance("ij/macro/Interpreter", "()V");
    future = javabridge.make_future_task(javabridge.run_script(
        script, dict(interp=interp, macro_text=macro_text, imp=imp)))
    return javabridge.execute_future_in_main_thread(future)
Beispiel #14
0
        def __init__(self):
            if service_classes is None:
                classes = None
                ctxt_fn = J.run_script("""new java.util.concurrent.Callable() {
                        call: function() {
                            return new Packages.net.imagej.ImageJ(false);
                        }
                    }""")
            else:
                classes = [
                    J.class_for_name(x)
                    for x in service_classes or REQUIRED_SERVICES
                ]
                classes = J.make_list(classes)
                ctxt_fn = J.run_script(
                    """new java.util.concurrent.Callable() {
                        call: function() {
                            return new Packages.net.imagej.ImageJ(classes);
                        }
                    }""", dict(classes=classes.o))

            self.o = J.execute_future_in_main_thread(
                J.make_future_task(ctxt_fn))
Beispiel #15
0
 def __init__(self):
     if service_classes is None:
         classes = None
         ctxt_fn = J.run_script(
             """new java.util.concurrent.Callable() {
                 call: function() {
                     return new Packages.net.imagej.ImageJ(false);
                 }
             }""")
     else:
         classes = [ 
             J.class_for_name(x) 
             for x in service_classes or REQUIRED_SERVICES]
         classes = J.make_list(classes)
         ctxt_fn = J.run_script(
             """new java.util.concurrent.Callable() {
                 call: function() {
                     return new Packages.net.imagej.ImageJ(classes);
                 }
             }""", dict(classes = classes.o))
     
     self.o = J.execute_future_in_main_thread(
         J.make_future_task(ctxt_fn))
def main(args):
    javabridge.activate_awt()
    script = """
    //--------------------------------------
    //
    // The anonymous callable runs on the thread
    // that started Java - that's the rule with AWT.
    //
    // The callable returns a Java Map whose keys
    // have the labels of objects like "qUp" for
    // the upward queue. Python can then fetch
    // whichever ones it wants and do Java stuff
    // with them.
    //
    //--------------------------------------
    new java.util.concurrent.Callable() {
        call: function() {
            importClass(javax.swing.SpringLayout);
            importClass(javax.swing.JFrame);
            importClass(javax.swing.JTextField);
            importClass(javax.swing.JButton);
            importClass(javax.swing.JScrollPane);
            importClass(javax.swing.JTextArea);
            importClass(java.util.Hashtable);
            importClass(java.awt.event.ActionListener);
            importClass(java.awt.event.WindowAdapter);
            importClass(java.util.concurrent.SynchronousQueue);
            
            d = new Hashtable();
            frame = new JFrame("Callbacks in Java");
            d.put("frame", frame);
            contentPane = frame.getContentPane();
            layout = new SpringLayout();
            contentPane.setLayout(layout);
            
            textField = new JTextField("'Hello, world.'", 60);
            d.put("textField", textField);
            contentPane.add(textField);
            
            execButton = new JButton("Exec");
            contentPane.add(execButton);
            
            evalButton = new JButton("Eval");
            contentPane.add(evalButton);
            
            result = new JTextArea("None");
            scrollPane = new JScrollPane(result)
            contentPane.add(scrollPane);
            d.put("result", result);
            
            //-----------------------------------------------------
            //
            // The layout is:
            //
            // [ textField] [execButton] [evalButton]
            // [    scrollPane                      ]
            //
            //-----------------------------------------------------

            layout.putConstraint(SpringLayout.WEST, textField,
                                 5, SpringLayout.WEST, contentPane);
            layout.putConstraint(SpringLayout.NORTH, textField,
                                 5, SpringLayout.NORTH, contentPane);

            layout.putConstraint(SpringLayout.WEST, execButton,
                                 5, SpringLayout.EAST, textField);
            layout.putConstraint(SpringLayout.NORTH, execButton,
                                 0, SpringLayout.NORTH, textField);
                                 
            layout.putConstraint(SpringLayout.WEST, evalButton,
                                 5, SpringLayout.EAST, execButton);
            layout.putConstraint(SpringLayout.NORTH, evalButton,
                                 0, SpringLayout.NORTH, textField);

            layout.putConstraint(SpringLayout.NORTH, scrollPane,
                                 5, SpringLayout.SOUTH, textField);
            layout.putConstraint(SpringLayout.WEST, scrollPane,
                                 0, SpringLayout.WEST, textField);
            layout.putConstraint(SpringLayout.EAST, scrollPane,
                                 0, SpringLayout.EAST, evalButton);
                                 
            layout.putConstraint(SpringLayout.EAST, contentPane,
                                 5, SpringLayout.EAST, evalButton);
            layout.putConstraint(SpringLayout.SOUTH, contentPane,
                                 20, SpringLayout.SOUTH, scrollPane);
            
            //------------------------------------------------
            //
            // qUp sends messages from Java to Python
            // qDown sends messages from Python to Java
            //
            // The communications protocol is that qUp sends
            // a command. For Exec and Eval commands, qUp sends
            // text and qDown must send a reply to continue.
            // For the Exit command, qUp sends the command and
            // Python must dispose of Java
            //
            //-------------------------------------------------
            
            qUp = new SynchronousQueue();
            qDown = new SynchronousQueue();
            d.put("qUp", qUp);
            d.put("qDown", qDown);
            
            //-----------------------------------------------
            //
            // Create an action listener that binds the execButton
            // action to a function that instructs Python to
            // execute the contents of the text field.
            //
            //-----------------------------------------------
            alExec = new ActionListener() {
                actionPerformed: function(e) {
                    qUp.put("Exec");
                    qUp.put(textField.getText());
                    result.setText(qDown.take());
                }
            };
            execButton.addActionListener(alExec);

            //-----------------------------------------------
            //
            // Create an action listener that binds the evalButton
            // action to a function that instructs Python to
            // evaluate the contents of the text field.
            //
            //-----------------------------------------------
            alEval = new ActionListener() {
                actionPerformed: function(e) {
                    qUp.put("Eval");
                    qUp.put(textField.getText());
                    result.setText(qDown.take());
                }
            };
            evalButton.addActionListener(alEval);
            
            //-----------------------------------------------
            //
            // Create a window listener that binds the frame's
            // windowClosing action to a function that instructs 
            // Python to exit.
            //
            //-----------------------------------------------
            wl = new WindowAdapter() {
                windowClosing: function(e) {
                    qUp.put("Exit");
                }
            };
            
            frame.addWindowListener(wl);

            frame.pack();
            frame.setVisible(true);
            return d;
        }
    };"""
    c = javabridge.run_script(script);
    f = javabridge.make_future_task(c)
    d = javabridge.execute_future_in_main_thread(f);
    d = javabridge.get_map_wrapper(d)
    qUp = d["qUp"]
    qDown = d["qDown"]
    frame = d["frame"]
    while True:
        cmd = javabridge.run_script("qUp.take();", dict(qUp=qUp))
        if cmd == "Exit":
            break
        text = javabridge.run_script("qUp.take();", dict(qUp=qUp))
        if cmd == "Eval":
            try:
                result = eval(text, globals(), locals())
            except Exception as e:
                result = "%s\n%s" % (str(e), traceback.format_exc())
            except:
                result = "What happened?"
        else:
            try:
                exec(text, globals(), locals())
                result = "Operation succeeded"
            except Exception as e:
                result = "%s\n%s" % (str(e), traceback.format_exc())
            except:
                result = "What happened?"
            
        javabridge.run_script("qDown.put(result);", 
                              dict(qDown=qDown, result = str(result)))
    javabridge.run_script("frame.dispose();", dict(frame=frame))
Beispiel #17
0
def main(args):
    javabridge.activate_awt()
    script = """
    //--------------------------------------
    //
    // The anonymous callable runs on the thread
    // that started Java - that's the rule with AWT.
    //
    // The callable returns a Java Map whose keys
    // have the labels of objects like "qUp" for
    // the upward queue. Python can then fetch
    // whichever ones it wants and do Java stuff
    // with them.
    //
    //--------------------------------------
    new java.util.concurrent.Callable() {
        call: function() {
            importClass(javax.swing.SpringLayout);
            importClass(javax.swing.JFrame);
            importClass(javax.swing.JTextField);
            importClass(javax.swing.JButton);
            importClass(javax.swing.JScrollPane);
            importClass(javax.swing.JTextArea);
            importClass(java.util.Hashtable);
            importClass(java.awt.event.ActionListener);
            importClass(java.awt.event.WindowAdapter);
            importClass(java.util.concurrent.SynchronousQueue);
            
            d = new Hashtable();
            frame = new JFrame("Callbacks in Java");
            d.put("frame", frame);
            contentPane = frame.getContentPane();
            layout = new SpringLayout();
            contentPane.setLayout(layout);
            
            textField = new JTextField("'Hello, world.'", 60);
            d.put("textField", textField);
            contentPane.add(textField);
            
            execButton = new JButton("Exec");
            contentPane.add(execButton);
            
            evalButton = new JButton("Eval");
            contentPane.add(evalButton);
            
            result = new JTextArea("None");
            scrollPane = new JScrollPane(result)
            contentPane.add(scrollPane);
            d.put("result", result);
            
            //-----------------------------------------------------
            //
            // The layout is:
            //
            // [ textField] [execButton] [evalButton]
            // [    scrollPane                      ]
            //
            //-----------------------------------------------------

            layout.putConstraint(SpringLayout.WEST, textField,
                                 5, SpringLayout.WEST, contentPane);
            layout.putConstraint(SpringLayout.NORTH, textField,
                                 5, SpringLayout.NORTH, contentPane);

            layout.putConstraint(SpringLayout.WEST, execButton,
                                 5, SpringLayout.EAST, textField);
            layout.putConstraint(SpringLayout.NORTH, execButton,
                                 0, SpringLayout.NORTH, textField);
                                 
            layout.putConstraint(SpringLayout.WEST, evalButton,
                                 5, SpringLayout.EAST, execButton);
            layout.putConstraint(SpringLayout.NORTH, evalButton,
                                 0, SpringLayout.NORTH, textField);

            layout.putConstraint(SpringLayout.NORTH, scrollPane,
                                 5, SpringLayout.SOUTH, textField);
            layout.putConstraint(SpringLayout.WEST, scrollPane,
                                 0, SpringLayout.WEST, textField);
            layout.putConstraint(SpringLayout.EAST, scrollPane,
                                 0, SpringLayout.EAST, evalButton);
                                 
            layout.putConstraint(SpringLayout.EAST, contentPane,
                                 5, SpringLayout.EAST, evalButton);
            layout.putConstraint(SpringLayout.SOUTH, contentPane,
                                 20, SpringLayout.SOUTH, scrollPane);
            
            //------------------------------------------------
            //
            // qUp sends messages from Java to Python
            // qDown sends messages from Python to Java
            //
            // The communications protocol is that qUp sends
            // a command. For Exec and Eval commands, qUp sends
            // text and qDown must send a reply to continue.
            // For the Exit command, qUp sends the command and
            // Python must dispose of Java
            //
            //-------------------------------------------------
            
            qUp = new SynchronousQueue();
            qDown = new SynchronousQueue();
            d.put("qUp", qUp);
            d.put("qDown", qDown);
            
            //-----------------------------------------------
            //
            // Create an action listener that binds the execButton
            // action to a function that instructs Python to
            // execute the contents of the text field.
            //
            //-----------------------------------------------
            alExec = new ActionListener() {
                actionPerformed: function(e) {
                    qUp.put("Exec");
                    qUp.put(textField.getText());
                    result.setText(qDown.take());
                }
            };
            execButton.addActionListener(alExec);

            //-----------------------------------------------
            //
            // Create an action listener that binds the evalButton
            // action to a function that instructs Python to
            // evaluate the contents of the text field.
            //
            //-----------------------------------------------
            alEval = new ActionListener() {
                actionPerformed: function(e) {
                    qUp.put("Eval");
                    qUp.put(textField.getText());
                    result.setText(qDown.take());
                }
            };
            evalButton.addActionListener(alEval);
            
            //-----------------------------------------------
            //
            // Create a window listener that binds the frame's
            // windowClosing action to a function that instructs 
            // Python to exit.
            //
            //-----------------------------------------------
            wl = new WindowAdapter() {
                windowClosing: function(e) {
                    qUp.put("Exit");
                }
            };
            
            frame.addWindowListener(wl);

            frame.pack();
            frame.setVisible(true);
            return d;
        }
    };"""
    c = javabridge.run_script(script)
    f = javabridge.make_future_task(c)
    d = javabridge.execute_future_in_main_thread(f)
    d = javabridge.get_map_wrapper(d)
    qUp = d["qUp"]
    qDown = d["qDown"]
    frame = d["frame"]
    while True:
        cmd = javabridge.run_script("qUp.take();", dict(qUp=qUp))
        if cmd == "Exit":
            break
        text = javabridge.run_script("qUp.take();", dict(qUp=qUp))
        if cmd == "Eval":
            try:
                result = eval(text, globals(), locals())
            except Exception as e:
                result = "%s\n%s" % (str(e), traceback.format_exc())
            except:
                result = "What happened?"
        else:
            try:
                exec(text, globals(), locals())
                result = "Operation succeeded"
            except Exception as e:
                result = "%s\n%s" % (str(e), traceback.format_exc())
            except:
                result = "What happened?"

        javabridge.run_script("qDown.put(result);",
                              dict(qDown=qDown, result=str(result)))
    javabridge.run_script("frame.dispose();", dict(frame=frame))
Beispiel #18
0
def main(args):
    javabridge.activate_awt()
    cpython = javabridge.make_instance(
        "org/cellprofiler/javabridge/CPython", "()V")
    script = """
    //--------------------------------------
    //
    // The anonymous callable runs on the thread
    // that started Java - that's the rule with AWT.
    //
    // The callable returns a Java Map whose keys
    // have the labels of objects like "qUp" for
    // the upward queue. Python can then fetch
    // whichever ones it wants and do Java stuff
    // with them.
    //
    //--------------------------------------
    new java.util.concurrent.Callable() {
        call: function() {
            importClass(javax.swing.SpringLayout);
            importClass(javax.swing.JFrame);
            importClass(javax.swing.JTextField);
            importClass(javax.swing.JButton);
            importClass(javax.swing.JScrollPane);
            importClass(javax.swing.JTextArea);
            importClass(java.util.Hashtable);
            importClass(java.util.ArrayList);
            importClass(java.util.concurrent.CountDownLatch);
            importClass(java.awt.event.ActionListener);
            importClass(java.awt.event.WindowAdapter);
            
            d = new Hashtable();
            signal = new CountDownLatch(1);
            d.put("signal", signal);
            frame = new JFrame("Callbacks in Java");
            d.put("frame", frame);
            contentPane = frame.getContentPane();
            layout = new SpringLayout();
            contentPane.setLayout(layout);
            
            textField = new JTextField("'Hello, world.'", 60);
            d.put("textField", textField);
            contentPane.add(textField);
            
            execButton = new JButton("Exec");
            contentPane.add(execButton);
            
            evalButton = new JButton("Eval");
            contentPane.add(evalButton);
            
            result = new JTextArea("None");
            scrollPane = new JScrollPane(result)
            contentPane.add(scrollPane);
            d.put("result", result);
            
            //-----------------------------------------------------
            //
            // The layout is:
            //
            // [ textField] [execButton] [evalButton]
            // [    scrollPane                      ]
            //
            //-----------------------------------------------------

            layout.putConstraint(SpringLayout.WEST, textField,
                                 5, SpringLayout.WEST, contentPane);
            layout.putConstraint(SpringLayout.NORTH, textField,
                                 5, SpringLayout.NORTH, contentPane);

            layout.putConstraint(SpringLayout.WEST, execButton,
                                 5, SpringLayout.EAST, textField);
            layout.putConstraint(SpringLayout.NORTH, execButton,
                                 0, SpringLayout.NORTH, textField);
                                 
            layout.putConstraint(SpringLayout.WEST, evalButton,
                                 5, SpringLayout.EAST, execButton);
            layout.putConstraint(SpringLayout.NORTH, evalButton,
                                 0, SpringLayout.NORTH, textField);

            layout.putConstraint(SpringLayout.NORTH, scrollPane,
                                 5, SpringLayout.SOUTH, textField);
            layout.putConstraint(SpringLayout.WEST, scrollPane,
                                 0, SpringLayout.WEST, textField);
            layout.putConstraint(SpringLayout.EAST, scrollPane,
                                 0, SpringLayout.EAST, evalButton);
                                 
            layout.putConstraint(SpringLayout.EAST, contentPane,
                                 5, SpringLayout.EAST, evalButton);
            layout.putConstraint(SpringLayout.SOUTH, contentPane,
                                 20, SpringLayout.SOUTH, scrollPane);
            
            //-----------------------------------------------
            //
            // Create an action listener that binds the execButton
            // action to a function that instructs Python to
            // execute the contents of the text field.
            //
            //-----------------------------------------------
            alExec = new ActionListener() {
                actionPerformed: function(e) {
                    try {
                        cpython.exec(textField.getText());
                        result.setText("OK");
                    } catch(err) {
                        result.setText(err.message);
                    }
                }
            };
            execButton.addActionListener(alExec);

            //-----------------------------------------------
            //
            // Create an action listener that binds the evalButton
            // action to a function that instructs Python to
            // evaluate the contents of the text field.
            //
            //-----------------------------------------------
            alEval = new ActionListener() {
                actionPerformed: function(e) {
                    try {
                        locals = new Hashtable();
                        jresult = new ArrayList();
                        locals.put("script", textField.getText());
                        locals.put("jresult", jresult);
                        script = "import javabridge\\n" +
                                 "result=eval(javabridge.to_string(script))\\n" +
                                 "jwresult=javabridge.JWrapper(jresult)\\n" +
                                 "jwresult.add(str(result))"
                        cpython.exec(script, locals, null);
                        result.setText(jresult.get(0));
                    } catch(err) {
                        result.setText(err.message);
                    }
                }
            };
            evalButton.addActionListener(alEval);
            
            //-----------------------------------------------
            //
            // Create a window listener that binds the frame's
            // windowClosing action to a function that instructs 
            // Python to exit.
            //
            //-----------------------------------------------
            wl = new WindowAdapter() {
                windowClosing: function(e) {
                    signal.countDown();
                }
            };
            
            frame.addWindowListener(wl);

            frame.pack();
            frame.setVisible(true);
            return d;
        }
    };"""
    c = javabridge.run_script(script, dict(cpython=cpython));
    f = javabridge.make_future_task(c)
    d = javabridge.execute_future_in_main_thread(f);
    d = javabridge.get_map_wrapper(d)
    frame = javabridge.JWrapper(d["frame"])
    signal = javabridge.JWrapper(d["signal"]);
    signal.await();
    frame.dispose();