我计划将 WCF-Console-Application 作为 Windows 服务运行。WCF-Console-Application 调用 FoxPro-DLL 来访问 FoxPro-DBF 中的数据(读取和写入)。不同的客户端(WPF-Application)应该使用 Console-Application 的 WCF-Service 来显示和编辑来自 FoxPro-DBF 的数据。
如果一次只有一个客户端调用 WCF-Console-Application,则一切正常。但是 WCF-Console-Application 不能正确处理来自多个客户端的并行调用。
WCF-Console-Application 由以下类组成:
main Class:派生自ServiceBase,既可以从控制台调用,也可以作为服务启动
公共类服务:ServiceBase { public ServiceHost serviceHost = null;
const string CONSOLE = "console"; public Service() { this.ServiceName = "ServiceTest"; } public static void Main(string[] args) { if (args.Length == 1 && args[0].Equals(CONSOLE)) { new Service().startConsole(); } else { ServiceBase.Run(new Service()); } } private void startConsole() { Console.WriteLine(string.Format("{0}::start Service...", GetType().FullName)); OnStart(null); Console.WriteLine(string.Format("{0}::ready (ENTER to stop)", GetType().FullName)); Console.ReadLine(); OnStop(); Console.WriteLine(string.Format("{0}::stop Service", GetType().FullName)); } protected override void OnStop() { if (this.serviceHost != null) { this.serviceHost.Close(); this.serviceHost = null; } } protected override void OnStart(string[] args) { if (this.serviceHost != null) { this.serviceHost.Close(); } this.serviceHost = new ServiceHost(typeof(Server.TestServer)); this.serviceHost.Open(); }
ServiceInstaller:安装Service,派生自Installer
[RunInstaller(true)]
public class InstallService : Installer
{
public InstallService()
{
process = new ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
service= new ServiceInstaller();
service.ServiceName = "ServiceTest";
service.Description = "ServiceTest";
service.DisplayName = "ServiceTest";
service.StartType = ServiceStartMode.Automatic;
Installers.Add(process);
Installers.Add(service);
}
}
- 用于访问 FoxPro-DLL 的静态类
public static class DataAccess
{
public static foxprotest.foxprotest accessData = new foxprotest.foxprotest();
}
- ITestServer,与 ServiceContract 的接口
[ServiceContract(Namespace = "http:/localhost.TestServer", SessionMode = SessionMode.Allowed)]
public interface ITestServer
{
[OperationContract]
String loadData(int id);
}
- TestServer,ITestServer的实现
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class TestServer : ITestServer
{
public String loadData(int id)
{
//set table
DataAccess.accessData.CTABLE = "patient";
//set ID
DataAccess.accessData.NPATIENT = id;
//fetch the data
DataAccess.accessData.FetchData();
//return data as XML
return DataAccess.accessData.CRESULT;
}
}
这是 App.Config 的样子:绑定设置为 netTcpBinding
<system.serviceModel>
<services>
<service name="Server.TestServer" behaviorConfiguration="MyFileServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8888/"/>
<add baseAddress="net.tcp://localhost:52/"/>
</baseAddresses>
</host>
<endpoint address="TestServer" binding="basicHttpBinding"
name="b" contract="Server.ITestServer" />
<endpoint address="TestServer" binding="netTcpBinding"
name="c" contract="Server.ITestServer" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyFileServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceThrottling maxConcurrentCalls="80" maxConcurrentSessions="80"
maxConcurrentInstances="80" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
我使用 svcutil.exe 为 WPF 应用程序生成 output.config 和 TestServer.cs。
FoxPro-DLL 构建为多线程 COM 服务器,已正确注册并使用 VFP9T.DLL。函数 loadData() 有一点延迟,用于测试并行调用。当我从多个 FoxPro 实例调用 DLL 时,一切都按预期工作。如果我将 dll 包含到 WPF 应用程序中并从那里调用它,它也可以工作。只有通过 WCF-Console-Application 进行多次调用,它才能正常工作。
当我通过控制台运行 WCF-Console-Application 并在 TestServer.LoadData() 的每一行之前创建一个 Console.WriteLine 时,第二个调用将 hangig 保持在前面
DataAccess.accessData.CTABLE = "patient";
直到第一次通话结束。最糟糕的是:当我进行并行调用时,返回的 XML 字符串是相同的。在使用 ID 进行第一次通话后,我立即使用不同的 ID 开始第二次通话。对于这两个调用,我都得到了带有第二个 ID 的 XML-String。
为了使 WCF-Console-Application 内的 FoxPro-DLL 并行调用正常工作,我可以更改什么?我尝试了 InstanceContextMode 和 ConcurrencyMode 的每种组合,但没有成功。我需要线程安全吗?如果是这样,我需要改变什么?该项目不能选择使用 ODBC 或 SQL-Server。
感谢您的任何建议和建议!
编辑:如果我重新启动 WCF-Console-Application,则只有第一个并行测试会提供错误的 XML 字符串。如果我进行第二次并行调用,则返回的 XML 字符串是正确的。但是并行调用的问题依然存在。