我正在运行Azure服务,该服务在单独的AppDomain中托管代码。我需要处理这些AppDomain中的服务配置更改。为此,我正在听RoleEnvironment.Changed事件。
但是,此事件仅在默认AppDomain中触发,而不在任何其他AppDomain中触发。但是,我可以通过在所有AppDomains中调用RoleEnvironment.GetConfigurationSettingValue来获取最新值。
我错过了什么,或者这是设计上的限制?
我需要让这个工作,所以我认为我需要开发一个解决方法,只有默认的AppDomain监听Changed事件,然后使用一些基本的IPC将任何更改传达给其他AppDomain。 有没有人对解决方法有更好的想法?
我已经创建了一个示例服务来说明我的问题:
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
}
}
}
我在Azure Compute Emulator中运行此服务,并使用csrun.exe
更新MySetting
值:
这是我在计算模拟器中看到的:
我还在Windows Azure上的实际部署中对此进行了测试,结果相同。
我真的没有看到任何理由(如果是设计),所以我认为这可能是一个错误。
我发现内部方法RoleEnvironment.InitializeCallbacks
用于注册Changed
事件的回调,每个进程只调用一次,而每个AppDomain调用一次。
只需执行以下操作即可通过RoleRuntimeBridge
中的公开Microsoft.WindowsAzure.ServiceRuntime.Implementation.Loader
课程调用此方法:
new RoleRuntimeBridge().Initialize(null);
但是,只有最后一个AppDomain执行此操作才会触发事件。因此,虽然这使我能够在“子”AppDomain中触发事件,但它们不再在默认的AppDomain中触发。
原因似乎是本机基础结构函数WaRegisterCallback
仅支持每个进程和回调类型的一个回调。
任何帮助或指示都会受到欢迎!
对于这个问题,我filed a bug on Microsoft Connect。