If you've asked a question, please remember to mark the best answer as 'accepted' by clicking the check mark next to your preferred answer. It looks like the checkmark to the left, and is right under the vote section. You'll gain some reputation and it helps us surface the best content.
3

I've hit a problem trying to enumerate the TrackingRates for my driver. The driver uses the LocalServer template as-is. Ascom Conform gets a similar error when trying to reference the tracking rates. Here's the Conform error message:

18:27:48.093 Tracking Read OK True 18:27:48.296 Tracking Write OK False 18:27:48.562 TrackingRates ERROR .NET - Exception:
System.NullReferenceException: Object reference not set to an instance of an object. at Conform.TelescopeTester.CheckProperties() in C:\Documents and Settings\Peter\My Documents\Visual Studio 2008\Projects\Conform\Conform\Devices\TelescopeTester.vb:line 1845

In my test client, the enumeration seems to fail when using the 'foreach' mechanism:

        ITrackingRates oTrackingRates;
        IAxisRates oAxisRates;

        sName = ASCOM.DriverAccess.Telescope.Choose("ASCOM.bwAstroPhysics.Telescope");
        if (sName.Length > 0)
            {
            f_oScope = new ASCOM.DriverAccess.Telescope(sName);
            f_oScope.Connected = true;
            // AxisRate enumeration works correctly...
            oAxisRates = f_oScope.AxisRates (ASCOM.Interface.TelescopeAxes.axisPrimary);
            foreach (IRate oRate in oAxisRates)
                MessageBox.Show((oRate.Maximum).ToString());
            oTrackingRates = f_oScope.TrackingRates;
            // This form of iteration on TrackingRates works correctly... 
            for (int iInx = 1; iInx <= oTrackingRates.Count; iInx++)
                MessageBox.Show(oTrackingRates[iInx].ToString());
            // This form fails because eRate is null
            foreach (DriveRates eRate in oTrackingRates)
                MessageBox.Show(eRate.ToString());

This seems like a bonehead problem to have, but I haven't figured it out.

3/9/10 Update: Per Bob's suggestion, I tested the same code in the DLL version of the driver, and the enumeration works fine. So the 'GetEnumerator' function in the out-of-proc server implementation seems to be failing for some reason. I was careful about this - the test app is literally the same one, using either the DLL or exe versions of the driver. I agree, there's nothing in LocalServer.cs that has anything to do with this, but the behavior of the driver code changes from one form of implementation to the other. Any other ideas?

flag
Remove the driver from the LocalServer, replace the registration code that you took out (hopefully just coommenting it out), register it, and test it by itself. It cannot be a LocalServer problem, it's a problem in the driver itself. For one thing, you should not have had to cast f_oScope.AxisRatesRates to set oAxisRates, and same for TrackingRates. – Bob Denny Mar 9 at 3:53
xRef: [ASCOM-78] teamserver.tigranetworks.co.uk:8010/browse/… – Tim Long Mar 11 at 14:08

1 Answer

3

I ran into the same issue in the Gemini driver. Solved it by implementing my own IEnumerator interface and returning it when GetEnumerator is called (note that this is an excerpt from the full class declaration):

public class TrackingRates : ITrackingRates, IEnumerable, IEnumerator
{        
    private DriveRates [] m_TrackingRates;
    private int _pos = -1;

    #region ITrackingRates Members

    public int Count
    {
        get { return m_TrackingRates.Length; }
    }

    public IEnumerator GetEnumerator()
    {
        return this as IEnumerator;
    }

    public DriveRates this[int Index]
    {
        get { return m_TrackingRates[Index - 1]; }  // 1-based
    }
    #endregion

    #region IEnumerator implementation

    public bool MoveNext()
    {
        if (++_pos >= m_TrackingRates.Length) return false;
        return true;
    }

    public void Reset()
    {
        _pos = -1;
    }

    public object Current
    {
        get
        {
            if (_pos < 0 || _pos >= m_TrackingRates.Length) throw new
                     System.InvalidOperationException();
            return m_TrackingRates[_pos];
        }
    }
    #endregion
}
link|flag
Thanks, Paul!! This works like a champ! I was going to head down this road myself, but you saved me the "experimentation" time. It looks like the problem might be some obscure COM-Interop behavior, maybe related to the use of enumerated values in the underlying array. I don't know - I'll leave it to a COM wizard to figure out :-). Thanks again very much! – Bruce Waddington Mar 10 at 2:33
+1 for including a code sample, very helpful. – Tim Long Mar 11 at 13:04
While this is a brilliant solution:-), it makes me uneasy. I'm unable to do the detailed research on this at the moment - but I'd like to know why the behavior changes when the objects are served via the LocalServer! – Bob Denny Mar 14 at 0:48

Your Answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.