C# RoleEnvironment已更改事件未在非默认AppDomain中触发
我正在运行一个Azure服务,它在不同的AppDomains中托管代码。我需要处理这些AppDomain中的服务配置更改。为了这个目的,我正在收听这个活动 但是,此事件仅在默认AppDomain中激发,而不在任何其他AppDomain中激发。但是,我可以通过调用所有AppDomains来获取最新的值 我是否遗漏了什么,或者这是设计的限制? 我需要让它工作,所以我想我需要开发一个解决方案,只有默认的AppDomain侦听事件,然后使用一些基本IPC将任何更改传达给其他AppDomain有人有更好的解决方法吗? 我创建了一个示例服务来说明我的问题:C# RoleEnvironment已更改事件未在非默认AppDomain中触发,c#,azure,appdomain,azure-role-environment,C#,Azure,Appdomain,Azure Role Environment,我正在运行一个Azure服务,它在不同的AppDomains中托管代码。我需要处理这些AppDomain中的服务配置更改。为了这个目的,我正在收听这个活动 但是,此事件仅在默认AppDomain中激发,而不在任何其他AppDomain中激发。但是,我可以通过调用所有AppDomains来获取最新的值 我是否遗漏了什么,或者这是设计的限制? 我需要让它工作,所以我想我需要开发一个解决方案,只有默认的AppDomain侦听事件,然后使用一些基本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
值:
这是我在compute emulator中看到的:
我也在WindowsAzure上的实际部署中对此进行了测试,得到了相同的结果
我真的看不出有什么原因(如果是设计的话),所以我认为这可能是一个bug
我发现内部方法RoleEnvironment.InitializeCallbacks
,用于注册Changed
事件的回调,每个进程只调用一次,而不是每个AppDomain调用一次
可以通过Microsoft.WindowsAzure.ServiceRuntime.Implementation.Loader中的publicRoleRuntimeBridge
类调用此方法,只需执行以下操作:
new RoleRuntimeBridge().Initialize(null);
但是,只有最后一个执行此操作的AppDomain才会触发事件。因此,虽然这使我能够在“子”AppDomain中激发事件,但它们不再在默认AppDomain中激发
这似乎是因为本机基础结构函数WaRegisterCallback
只支持每个进程和回调类型一次回调
任何帮助或指点都将被感谢
我对这个问题很感兴趣。这不是对你问题的回答,但模拟器可能只是有缺陷,在这方面无法模仿真正的云。只有在真实云中重现的问题才值得浪费时间。@sharptooth,这个问题在真实云中也存在,所以它不是针对模拟器的。