Click or drag to resize

Controlling Locking

By default, the Nimbus code weaver will ensure that driver methods, properties and events have the following thread synchronization characteristics:

  1. Access to the driver method, property or event will be serialized such that only one thread at a time may enter the body of the method, property or event for the same instance of a driver object.

  2. An infinite timeout will be used to wait for ownership of the underlying lock.

The code weaver accomplishes this by injecting a call to the AcquireLock method defined within the Nimbus Class Library, which in turn uses the IVI.NET standard LockManager class.

For example, consider the driver property shown below, which shows a common use of the DriverProperty attribute.

C#
[DriverProperty]
public TriggerSource Source
{
    get
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR?\n");
        Acme.Acme4321.TriggerSource value;
        this.IO.FormattedIO.Scanf("%s", out value);

        return value;
    }
    set
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR %s\n", value);
    }
}

When built and viewed in .NET Reflector, that property would be implemented as shown in Figure 1.

Figure 1: Default Locking with the DriverProperty Attribute (as seen in .NET Reflector)

Notice that, as seen in the disassembled code, the Nimbus code weaver has injected a call to AcquireLock without any parameters, which implies a willingness to wait for an unbounded period of time for entry into the body of the property.

This default behavior can be modified in two ways, depending on your needs:

  • A non-infinite timeout may be specified. The procedure for making this customization is described here.

  • Locking may be disabled altogether. The procedure for making this customization is described here.

Specify a non-infinite lock timeout

  1. From the driver designer, right click on the property, method or event for which you wish to customize locking and select Go to Implementation.

  2. Locate the DriverProperty, DriverMethod or DriverEvent attribute that appears above the implementation.

  3. Update the attribute declaration to set the named parameter LockTimeoutMilliseconds to a non-zero value that expresses the maximum amount of time, in milliseconds, that blocked threads should wait before entering the associated method, property or event body. The following example illustrates setting the maximum lock timeout for a driver property to 5000 milliseconds.

    C#
    [DriverProperty(LockTimeoutMilliseconds = 5000)] // Non-infinite lock timeout specified.
    public TriggerSource Source
    {
        get
        {
            this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR?\n");
            Acme.Acme4321.TriggerSource value;
            this.IO.FormattedIO.Scanf("%s", out value);
    
            return value;
        }
        set
        {
            this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR %s\n", value);
        }
    }
  4. Rebuild the driver.

    When built and viewed in .NET Reflector, that property would be implemented as shown in Figure 2.

    Figure 2: Specifying a non-Infinite Lock Timeout (as seen in .NET Reflector)

    Notice that, as seen in the disassembled code, the Nimbus code weaver has injected a call to AcquireLock(PrecisionTimeSpan), using the timeout value expressed in the DriverProperty attribute.

    Note Note

    If this technique is used, the underlying IVI.NET LockManager will raise an exception if the calling thread cannot acquire the requested lock within the user-defined timeout period.

Disable locking completely

  1. From the driver designer, right click on the property, method or event for which you wish to customize locking and select Go to Implementation.

  2. Locate the DriverProperty, DriverMethod or DriverEvent attribute that appears above the implementation.

  3. Update the attribute declaration to set the named parameter Lock to false, as shown below.

    C#
    [DriverProperty(Lock = false)] // Locking disabled.
    public TriggerSource Source
    {
        get
        {
            this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR?\n");
            Acme.Acme4321.TriggerSource value;
            this.IO.FormattedIO.Scanf("%s", out value);
    
            return value;
        }
        set
        {
            this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR %s\n", value);
        }
    }
  4. Rebuild the driver.

    Figure 3 shows the corresponding disassembled view in .NET Reflector.

    Figure 3: Disable Locking (as seen in .NET Reflector)

    Notice that the code weaver no longer performs any sort of thread synchronization.

    Caution note Caution

    Disabling lock acquisition completely is an advanced technique, and should only be used in cases where the developer is certain that the code being invoked does not need any thread synchronization (for example, a property that simply returns a constant value), or if the developer wants to use a different thread synchronization technique (for example, using the standard .NET Framework Class Library ReaderWriterLock).

See Also

Download a complete CHM version of this documentation here.