【发布时间】:2014-08-20 04:02:26
【问题描述】:
我是新来的,希望能找到解决问题的方法。问题背景如下:
- 我正在尝试构建一个专家系统,该系统构成一个与 Swi-prolog 交互的 C# 前端。
- 我已经下载了
SwiPlCs.dll(一个将 .NET 语言与 Swi-Prolog 连接起来的 CSharp 类库) - 并在我创建的 Visual Studio 项目(Win 表单应用程序)中添加了对它的引用,以测试我是否可以从 c# 查询 prolog(我按照文档中使用的示例找到了 here)。
- 效果很好。
- 然后,在一个更复杂的场景中,我构建了一个 WCF 服务,它将充当 Swi-Prolog 和 C# 客户端应用程序(它使用该服务)之间的中间层。
- 服务托管在 IIS 7.0 中。
- 为了简单起见,假设我的服务包含三种方法。
- 第一种方法初始化prolog引擎,查询prolog源文件,然后查询文件。
- 第二种方法执行另一个查询。
- 第三个方法调用 PlCleanup()。
方法#1:
public void LaunchAssessment()
{
Dictionary<string, string> questions = new Dictionary<string, string>();
#region : Querying prolog using SwiPlCs
try
{
if (!PlEngine.IsInitialized)
{
String[] param = { "-q" };
PlEngine.Initialize(param);
PlQuery.PlCall("consult('D:/My FYP Work/initialAssessment')");
using (var q = new PlQuery("go(X, Y)"))
{
foreach (PlQueryVariables v in q.SolutionVariables)
{
questions.Add("name", v["X"].ToString());
questions.Add("age", v["Y"].ToString());
}
}
}
}
catch (SbsSW.SwiPlCs.Exceptions.PlException exp)
{
throw new FaultException<PrologFault>(new PrologFault(exp.Source), exp.MessagePl);
}
#endregion
Callback.PoseQuestion(questions, ResponseType.None);
}
方法#2:
public void DetermineAgeGroup(int age)
{
//Determine age group
string age_group = string.Empty;
try
{
using (var query = new PlQuery("age_group(" + age + ", G)"))
{
foreach (PlQueryVariables v in query.SolutionVariables)
age_group += v["G"].ToString();
}
}
catch (SbsSW.SwiPlCs.Exceptions.PlException exp)
{
throw new FaultException<PrologFault>(new PrologFault(exp.Source), exp.MessagePl);
}
//Check whether age_group is found or not
if (string.IsNullOrEmpty(age_group))
{
throw new FaultException<NoSolutionFoundFault>(new NoSolutionFoundFault("No solution found"), "Age specified exceeds the diagnosis range!");
}
else
{
Callback.RespondToUser(age_group, ResponseType.Age);
}
}
方法#3:
public void QuitProlog()
{
if (PlEngine.IsInitialized)
{
PlEngine.PlCleanup();
}
}
客户端调用第一个方法就好了,第一个查询的结果成功返回。当客户端尝试调用第二种方法时,会引发异常并带有消息(尝试读取或写入受保护的内存),这会导致应用程序冻结。我检查了事件查看器,这就是我得到的:
Application: w3wp.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
堆栈:
at SbsSW.SwiPlCs.SafeNativeMethods.PL_new_term_ref()
at SbsSW.SwiPlCs.PlQuery..ctor(System.String, System.String)
at SbsSW.SwiPlCs.PlQuery..ctor(System.String)
at PrologQueryService.PrologQueryService.DetermineAgeGroup(Int32)
【问题讨论】:
-
在哪一行抛出异常?
-
在调用DetermineAgeGroup(int age) 方法时。在这一行中:使用 (var query = new PlQuery("age_group(" + age + ", G)"))
-
您的 WCF 服务在哪种实例化模式下工作(PerCall、Single、Per-Session)?
-
设置为 Per-Session 且 ConcurrencyMode 为单一
-
嗯。 PerSession 和 Single 并发模式是正确的。尝试编译所有针对 x86 平台的程序集。有时,此类互操作性问题可能是由针对 x64 平台的编译引起的。
标签: c# .net wcf swi-prolog