Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • STATA C# integration - OnFinish

    Dear Forum Members,

    I am realatively new to STATA and new to Visual C#. As a part of a school assignment I would like to integrate them, I got stuck at OnFinish event.
    I am using this manual, but it is only available for VB not C#:
    http://www.stata.com/automation/

    I could implement the creation of the stata object (stata.StataOLEApp), and I can run commands (DoCommand()), my problem is the following:

    I am creating an easy user interface (WPF) and I would like to populate a combobox from the results of a Stata command. I send the command to stata with DoCommand which creates a variable when ready. I read the value of that variable with VariableData() method and use that value to populate the combobox. However, my program tries to populate the combobox before Stata finishes the command, so it ends up empty. I would like to pause the thread of my program until Stata finishes the command, for this I would like to use the UtilIsStataFreeEvent() method and catch the OnFinish event. Nevertheless, I am stuck at this point, the manual only illustrates VB not C#, and I am really new to C# event handling.

    My code:
    I created an event handler:

    public void HandleCustomEvent(object sender, EventArgs a)
    {
    MessageBox.Show("Finito");
    }

    stata.StataOLEApp statapp = new stata.StataOLEApp();
    ... Stata commands
    statapp.UtilIsStataFreeEvent();
    statapp.OnFinish += new EventHandler(HandleCustomEvent);

    But I get the error: Error 1 Cannot implicitly convert type 'System.EventHandler' to 'stata._IStataOLEAppEvents_OnFinishEventHandler'

    Though based on this: http://msdn.microsoft.com/en-us/library/ms366768.aspx I should wirte: statapp.OnFinish += new CustomEventHandler(HandleCustomEvent);
    But this CustomEventHandler is defined in the stata namespace?

    Excuse me, I am new to C# and OOP too. Could you please help me with an example? Somebody here has some experience with this? Thank you!

  • #2
    The following VC# code snippet shows how to use DoCommand() to generate a variable, then use the values of the variable to populate a combobox:

    Code:
    private void butRunCommand_Click(object sender, RoutedEventArgs e)
    {
        // generate variable
        stataobj.DoCommand("clear") ;
        stataobj.DoCommand("set more off") ;
        stataobj.DoCommand("set obs 5")  ;
        stataobj.DoCommand("gen y = _n") ;
    
        // get the values of the variable
        Double[] varData = stataobj.VariableDataFromName("y", 1, 5) ;
        List<String> s = new List<String>() ;
        for (int i = 0; i < 5; i++)
        {
            s.Add(varData[i].ToString()) ;
        }
    
        // populate a combobox
        cmbValues.ItemsSource = s ;
        cmbValues.SelectedIndex = 0 ;
    }
    I suspect you were trying to run the DoCommand() on a worker thread and VariableData() on the GUI thread, hence VariableData() was called before Stata finished the command. If you have to do that, you will be responsible to the synchronization of the worker thread and the GUI thread in your C# code.

    Using DoCommandAsync() in WPF needs some extra work due to WPF does not supports Application.DoEvents() on the GUI threads. The following code snippet shows how to use DispatcherFrame to simulate DoEvents() and how to handle OnFinsh event from StataOLE.

    Code:
    public stata.StataOLEApp stataobj;
    public bool isStataFree ;
    
    public MainWindow()
    {
        InitializeComponent();
        stataobj = new stata.StataOLEApp();
    
        // add event to be handled
        stataobj.OnFinish += new stata._IStataOLEAppEvents_OnFinishEventHandler(stataobj_OnFinish);
    }
    
    // handles onFinish event
    void stataobj_OnFinish(int noCommand)
    {
        isStataFree = true ;
    }
    
    
    private void butRunCommandAsync_Click(object sender, RoutedEventArgs e)
    {
        isStataFree = false;
    
        // run command asynchronously
        stataobj.DoCommandAsync("clear");
        stataobj.DoCommandAsync("set more off");
        stataobj.DoCommandAsync("set obs 5");
        stataobj.DoCommandAsync("gen y = _n*2");
    
        // fire the event
        stataobj.UtilIsStataFreeEvent() ;
    
        // wait for the OnFinish event
        while(isStataFree == false) {
            // allow events to pass
            this.DoEvents();
        }
    
        // get the values of the variable
        Double[] varData = stataobj.VariableDataFromName("y", 1, 5);
        List<String> s = new List<String>();
        for (int i = 0; i < 5; i++)
        {
            s.Add(varData[i].ToString());
        }
    
        // populate the combobox
        cmbValues.ItemsSource = s;
        cmbValues.SelectedIndex = 0;
    }
    
    // use DispatcherFrame to simulate DoEvents()
    public void DoEvents()
    {
        DispatcherFrame frame = new DispatcherFrame();
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
            new DispatcherOperationCallback(ExitFrame), frame);
        Dispatcher.PushFrame(frame);
    }
    
    public object ExitFrame(object f)
    {
        ((DispatcherFrame)f).Continue = false;
    
        return null;
    }

    Comment


    • #3
      Thank you Kevin, it was really useful!

      Comment

      Working...
      X