4

I'm running an Azure service that host code in separate AppDomains. I need to handle service configuration changes in these AppDomains. For this purpose I'm listening to the RoleEnvironment.Changed event.

However, this event is only fired in the default AppDomain not in any other AppDomain. I can, however, get up-to-date values by calling RoleEnvironment.GetConfigurationSettingValue in all AppDomains.

Am I missing something, or is this a limitation by design?

I need to get this working so I'm thinking that I need to develop a workaround where only the default AppDomain listen to the Changed event and then communicate any changes to the other AppDomains using some basic IPC. Does anyone have a better idea for a workaround?

I've created a sample service to illustrate my problem:

public class WorkerRole : RoleEntryPoint
{
    public override void Run()
    {
        AppDomain.CreateDomain("MySubdomain", null,
             AppDomain.CurrentDomain.SetupInformation).DoCallBack(() =>
        {
            WorkerRole.EnableDevFabricTraceListener();
            new Thread(WorkerRole.WorkerThreadProc).Start("CHILD");
        });

        WorkerRole.WorkerThreadProc("MAIN");
    }

    private static void WorkerThreadProc(object id)
    {
        Trace.TraceInformation(string.Format(
            "[{0}] Starting", id), "Information");

        RoleEnvironment.Changed += (sender, args) =>
        {
            Trace.TraceInformation(string.Format(
                "[{0}] Role environment changed!", id), "Information");
        };

        string prevValue = null;

        while (true)
        {
            string currValue = RoleEnvironment.GetConfigurationSettingValue(
                 "MySetting");

            if (prevValue != currValue)
            {
                Trace.TraceInformation(string.Format(
                    "[{0}] MySetting={1}", id, currValue), "Information");
                prevValue = currValue;
            }

            Thread.Sleep(1000);
        }
    }

    // This is just a hack to enable tracing to the Azure Compute Emulator in
    // other app domains.
    private static void EnableDevFabricTraceListener()
    {
        try
        {
            const string className = "Microsoft.ServiceHosting.Tools.DevelopmentFabric.Runtime.DevelopmentFabricTraceListener";
            const string assemblyName = "Microsoft.ServiceHosting.Tools.DevelopmentFabric.Runtime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";

            var assembly = Assembly.Load(assemblyName);
            var computeEmulatorTraceListenerType = assembly.GetType(className);
            var computeEmulatorTraceListener = (TraceListener)Activator.CreateInstance(computeEmulatorTraceListenerType);

            Trace.Listeners.Add(computeEmulatorTraceListener);
        }
        catch
        {
            // suppressed
        }
    }
}

I'm running this service in the Azure Compute Emulator and use csrun.exe to update the MySetting value:

Using CSRUN.EXE to update the setting

This is what I see in the compute emulator:

Trace output in Azure Compute Emulator

I've also tested this in a real deployment on Windows Azure with the same results.

I don't really see any reason for this (if it is by design), so I'm thinking that it might be a bug.

I've found that the internal method RoleEnvironment.InitializeCallbacks, which is used to register callbacks for the Changed event, is only invoked once per process and not once per AppDomain.

It is possible to invoke this method via the public RoleRuntimeBridge class in Microsoft.WindowsAzure.ServiceRuntime.Implementation.Loader by simply doing:

new RoleRuntimeBridge().Initialize(null);

However, only the last AppDomain to do this will have events fired. So while this enables me to get events fired in the "child" AppDomain, they are no longer fired in the default AppDomain.

The reason for this seem to be that the native infrastructure function WaRegisterCallback only support one callback per process and callback type.

Any help or pointers would be appriciated!

I've filed a bug on Microsoft Connect for this issue.

Mårten Wikström
  • 11,074
  • 5
  • 47
  • 87
  • Not an answer to your question, but the emulator can be simply buggy and not mimic the real cloud in this aspect. Only problems reproduced in the real cloud are worth wasting time on. – sharptooth Feb 25 '14 at 13:08
  • @sharptooth, this problem exist also in the real cloud, so it is not specific for the emulator. – Mårten Wikström Feb 25 '14 at 13:58

0 Answers0