自承载 WCF 服务中的状态丢失 InstanceContextMode.Single
State inside self-hosted WCF service being lost with InstanceContextMode.Single
我正在使用 WCF 服务并自行托管它,因为并非所有内容都包含在服务本身中(一些外部事件发生在服务之外):
- WCF 服务,我在 C# 控制台应用程序中自行托管它。当 WCF 客户端连接时,他们调用登录函数,我(尝试!)通过
GetCallbackChannel
存储他们的回调
- 第 3 方 DLL,它通过来自库的不同线程上的委托回调我的控制台
- 在这个控制台回调中,我然后调用 WCF 服务池,然后将其传递给 WCF 服务,然后 WCF 服务通过回调合同向所有连接的客户端广播。
客户端连接一切正常,调用登录,我保存回调接口对象
然而,当我从我的服务访问代码时,我发现它是一个全新的对象并且我的 _endPointMap 是空的(尽管我将它存储在客户端调用的登录方法中):
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : IService, IEndpointNotifier
{
public readonly TwoWayDictionary<string, IClientCallback> _endpointMap = new TwoWayDictionary<string, IClientCallback>();
// called by WCF client when they click the login button - it works
public void Login(string username)
{
var callback = OperationContext
.Current
.GetCallbackChannel<IClientCallback>();
_endpointMap.AddOrUpdate(username, callback);
list.Add(username);
}
// called by the WCF self-host console app
public void IEndpointNotifier.Notify(string info, string username)
{
// at this point my list _endpointMap is empty despite
// having received a Login previously and adding to the
// list. so i am unable to call my clients back!!
_endPointMap.Count(); // is 0 at this point?!!
}
}
我的主控制台应用程序启动服务也很好,如下所示:
static void Main(string[] args)
{
var service = new Service();
var host = new ServiceHost(service);
// between the above line and the task below calling
// service.Notify I click a number of times on client
// which calls the Login method
Task.Run(() =>
{
for (var i = 0; i < 3; i++)
{
Thread.Sleep(10000);
// at this point, service seems like a new object?!
// any data saved in the list member will be lost,
// and will only see the single entry from time of
// construction
service.Notify("hi","bob");
}
});
Console.ReadLine();
}
请提问
该对象似乎与之前操作(从客户端登录时)中修改的对象完全不同 - 有什么方法可以告诉我实际正在查看的服务对象(相当于旧的 C++ 时代并查看 this
) 的地址指针?
单例属性似乎被忽略了[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
知道我做错了什么(为什么内部列表变量不断重置)?
WCF 服务不能自包含。如何根据最佳实践实现 WCF 自托管应用程序与 WCF 服务之间的通信,或者这是在滥用 WCF 及其设计目的(考虑范围等时)?
我在构造函数中使用一些虚拟值设置了断点。该断点仅在我构造它时第一次被击中。当我通过 service.Notify 方法进入对象时,尽管对象看起来是新的(成员为空),但构造函数断点未命中 - 怎么会这样?
我在我控制的静态全局成员变量后面托管了第 3 方应用程序。所以我负责第 3 方库和正常 wcf 调用之间的所有通信和状态以及清理。我负责第 3 方应用程序的线程生命周期。如果我创建它们,我必须关闭它们。在我自己的列表中保留引用。
它就像是一个单独的应用程序,但它们恰好在同一个进程中 space。与第 3 方应用程序之间的所有通信都由我正式控制。
您可能需要一个线程来查找已完成或废弃的第 3 方对象,以便在正常的 wcf 消息处理之外自行杀死它们。
这使得 wcf 部分成为一个没有特殊声明的普通线程(线程池)概念。
旁注:
我会取出循环并在您的简单模型中将其设为两行。
service.Notify("hi")
Console.ReadLine();
这将公开您的对象生命周期详细信息,而不是将它们隐藏 3 秒。
我发现为什么没有保存这些值...我的 WCF 客户端代理连接到 VS WCF 服务主机,而不是我在代码中的主机!
当我在服务栏托盘中看到 WCF 服务主机 运行 时,我注意到了这一点。
我通过右键单击 WCF Project
-> Properties
-> WCF Options
-> 未勾选的 Start WCF Service Host when debugging another project in the same solution
禁用了为 WCF .svc 服务启动的 WCF 服务主机
我正在使用 WCF 服务并自行托管它,因为并非所有内容都包含在服务本身中(一些外部事件发生在服务之外):
- WCF 服务,我在 C# 控制台应用程序中自行托管它。当 WCF 客户端连接时,他们调用登录函数,我(尝试!)通过
GetCallbackChannel
存储他们的回调
- 第 3 方 DLL,它通过来自库的不同线程上的委托回调我的控制台
- 在这个控制台回调中,我然后调用 WCF 服务池,然后将其传递给 WCF 服务,然后 WCF 服务通过回调合同向所有连接的客户端广播。
客户端连接一切正常,调用登录,我保存回调接口对象
然而,当我从我的服务访问代码时,我发现它是一个全新的对象并且我的 _endPointMap 是空的(尽管我将它存储在客户端调用的登录方法中):
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : IService, IEndpointNotifier
{
public readonly TwoWayDictionary<string, IClientCallback> _endpointMap = new TwoWayDictionary<string, IClientCallback>();
// called by WCF client when they click the login button - it works
public void Login(string username)
{
var callback = OperationContext
.Current
.GetCallbackChannel<IClientCallback>();
_endpointMap.AddOrUpdate(username, callback);
list.Add(username);
}
// called by the WCF self-host console app
public void IEndpointNotifier.Notify(string info, string username)
{
// at this point my list _endpointMap is empty despite
// having received a Login previously and adding to the
// list. so i am unable to call my clients back!!
_endPointMap.Count(); // is 0 at this point?!!
}
}
我的主控制台应用程序启动服务也很好,如下所示:
static void Main(string[] args)
{
var service = new Service();
var host = new ServiceHost(service);
// between the above line and the task below calling
// service.Notify I click a number of times on client
// which calls the Login method
Task.Run(() =>
{
for (var i = 0; i < 3; i++)
{
Thread.Sleep(10000);
// at this point, service seems like a new object?!
// any data saved in the list member will be lost,
// and will only see the single entry from time of
// construction
service.Notify("hi","bob");
}
});
Console.ReadLine();
}
请提问
该对象似乎与之前操作(从客户端登录时)中修改的对象完全不同 - 有什么方法可以告诉我实际正在查看的服务对象(相当于旧的 C++ 时代并查看
this
) 的地址指针?单例属性似乎被忽略了
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
知道我做错了什么(为什么内部列表变量不断重置)?WCF 服务不能自包含。如何根据最佳实践实现 WCF 自托管应用程序与 WCF 服务之间的通信,或者这是在滥用 WCF 及其设计目的(考虑范围等时)?
我在构造函数中使用一些虚拟值设置了断点。该断点仅在我构造它时第一次被击中。当我通过 service.Notify 方法进入对象时,尽管对象看起来是新的(成员为空),但构造函数断点未命中 - 怎么会这样?
我在我控制的静态全局成员变量后面托管了第 3 方应用程序。所以我负责第 3 方库和正常 wcf 调用之间的所有通信和状态以及清理。我负责第 3 方应用程序的线程生命周期。如果我创建它们,我必须关闭它们。在我自己的列表中保留引用。
它就像是一个单独的应用程序,但它们恰好在同一个进程中 space。与第 3 方应用程序之间的所有通信都由我正式控制。
您可能需要一个线程来查找已完成或废弃的第 3 方对象,以便在正常的 wcf 消息处理之外自行杀死它们。
这使得 wcf 部分成为一个没有特殊声明的普通线程(线程池)概念。
旁注: 我会取出循环并在您的简单模型中将其设为两行。
service.Notify("hi") Console.ReadLine();
这将公开您的对象生命周期详细信息,而不是将它们隐藏 3 秒。
我发现为什么没有保存这些值...我的 WCF 客户端代理连接到 VS WCF 服务主机,而不是我在代码中的主机!
当我在服务栏托盘中看到 WCF 服务主机 运行 时,我注意到了这一点。
我通过右键单击 WCF Project
-> Properties
-> WCF Options
-> 未勾选的 Start WCF Service Host when debugging another project in the same solution
禁用了为 WCF .svc 服务启动的 WCF 服务主机