Help - forcing .net events to fire on main thread.

Posted by Admin on 18-Jul-2013 08:26

Hi,

I have a third party .Net dll called pcTAFMO that publishes an event. The problem is that it publishes it on a worker thread which openedge can not cope with and the parameters do not conform to the .Net framework recommendations. So I have wrapped this dll in my own c# dll and I am trying to force the event to fire on the main thread and use the correct parameter structure i.e.(System.Object sender, System.EventArgs e). With the new dll I am able to subscribe to my new wrapper event from openedge but the event never seems to make it to the openedge side.

I am using the Dispatcher class to identify the main thread storing in on creation of the wrapper class. I subscribe to the third party event and republish it to my own event forcing it onto the main thread using the invoke() method on the dispatcher class.

Has anybody ever got this working? Am I doing anything wrong?

Here is an example of the c# code:-

namespace DotNetWrapper{

public class PCTouch{

pcTAFMO.APIClass _TAFMOAPI;

public delegate void InvokeSurrenderHandler(object sender, SurrenderEventArgs args);
public event InvokeSurrenderHandler OESurrender;
private Dispatcher _uiDispatcher;

public PCTouch(){
    _TAFMOAPI = new pcTAFMO.APIClass();
    _TAFMOAPI.Surrender += processSurrender;
    _uiDispatcher = Dispatcher.CurrentDispatcher;            
        }

  private void processSurrender(int p_iReason, string p_sMessage){
      if (OESurrender != null){
         if (Dispatcher.CurrentDispatcher != _uiDispatcher){
             _uiDispatcher.Invoke(OESurrender, this, new SurrenderEventArgs(p_iReason, p_sMessage));
         }
         else{
            OESurrender(this, new SurrenderEventArgs(p_iReason, p_sMessage));
            }
     }
  }

  public class SurrenderEventArgs : EventArgs
    {
        private int myReason;
        private string myMessage;
        public int Reason { get { return myReason; } set { myReason = value; } }
        public string Message { get { return myMessage; } set { myMessage = value; } }
        public SurrenderEventArgs(int p_iReason, string p_sMessage)
        {
            this.Reason = p_iReason;
            this.Message = p_sMessage;

        }
    }

}

Here is the ABL Code:-

 define private variable m_oPCTouchAPI as new DotNetWrapper.PCTouch().

constructor Test():

  m_oPCTouchAPI = new DotNetWrapper.PCTouch().
  m_oPCTouchAPI:OESurrender:Subscribe(processSurrender).

end.

    /*------------------------------------------------------------------------------
     Purpose:
     Notes:
    ------------------------------------------------------------------------------*/

    method private void processSurrender(sender as System.Object, e as DotNetWrapper.SurrenderEventArgs):
        message "processSurrender" e:Reason e:Message
        view-as alert-box.
        return.

        catch err as Progress.Lang.Error:
             message err:getMessage(1)
             view-as alert-box.
        end catch.

    end method.

Thanks,

Craig

All Replies

Posted by Admin on 18-Jul-2013 11:33

You may develop a System.Windows.Forms.Control derived C# class for that purpose.

Here's a sample. The OutputDataReceived event of the oProcess is raised from a background thread.

The OnDataAvailable event will be synchronized into the foreground (UI) thread and can be handled from the ABL.

        public event EventHandler DataAvailable;

        void oProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)

        {

            OnDataAvailable(EventArgs.Empty);

        }

        protected void OnDataAvailable (EventArgs e)

        {

            if (this.InvokeRequired)

                this.BeginInvoke(new Action (OnDataAvailable), new[] { e });

            else

                this.DataAvailable(this, e);

        }

Posted by Admin on 19-Jul-2013 02:06

HI Mike,

Thanks for the reply. I will give it a go.

Thanks,

Craig

Posted by jquerijero on 06-Aug-2013 16:22

Try

if (!Dispatcher.CurrentDispatcher.Equals(_uiDispatcher))

{

}

instead of

if (Dispatcher.CurrentDispatcher != _uiDispatcher)

{

}

Posted by Admin on 08-Aug-2013 02:50

Actually - Both ways work fine. It was a debug alert-box that was stopping the event from coming through. Once I removed the alert-box the it all worked.

Posted by christian.bryan@capita.co.uk on 08-Nov-2017 12:40

This saved my bacon ...

I was just missing the _uiDispatcher.Invoke() part if i wasn't on the main / UI thread.

This thread is closed