.net 在没有“持久性服务”的情况下管理工作流生命周期

.net 在没有“持久性服务”的情况下管理工作流生命周期,.net,workflow,workflow-foundation,.net,Workflow,Workflow Foundation,我现在正在使用WindowsWF来实现状态机的简单方式。事实上,我甚至没有使用状态机,我使用的是顺序工作流。最终,我将放弃WF,转而使用其他方法,但由于我已经让代码正常工作,所以我需要让Abort、Suspend和Resume方法正常工作 我的应用程序生成一个线程,然后该线程生成另一个拥有WorkflowInstance的线程。我的GUI中有Abort、Pause和Resume按钮,它们最终分别调用WorkflowInstance的Abort、Suspend和Resume方法 问题是,当我这样做

我现在正在使用WindowsWF来实现状态机的简单方式。事实上,我甚至没有使用状态机,我使用的是顺序工作流。最终,我将放弃WF,转而使用其他方法,但由于我已经让代码正常工作,所以我需要让Abort、Suspend和Resume方法正常工作

我的应用程序生成一个线程,然后该线程生成另一个拥有WorkflowInstance的线程。我的GUI中有Abort、Pause和Resume按钮,它们最终分别调用WorkflowInstance的Abort、Suspend和Resume方法

问题是,当我这样做时,我会收到一个非常大且可怕的消息框,上面写着:

工作流宿主环境没有工作流实例上的操作所需的持久性服务

还有一个很好的堆栈跟踪等等。现在,我在中查找了这些方法,他的一个示例调用了这些方法,但没有提到持久性服务。但是,他的示例调用在WorkflowRuntime的范围内,即他这样调用它们:

using(WorkflowRuntimeManager manager = new WorkflowRuntimeManager(new WorkflowRuntime("WorkflowRuntime")))
{
  manager.WorkflowRuntime.StartRuntime();
  WorkflowInstanceWrapper instance = manager.StartWorkflow(typeof(SharedWorkflows.Workflow1), null);
  instance.Suspend("Manually suspended");
  instance.Resume();
  waitHandle.WaitOne();
}
WorkflowInstance instance = WorkflowRuntimeSingleton.Instance.workflow_runtime.CreateWorkflow(typeof(SharedWorkflows.Workflow1), null);
instance.Start();
instance.Suspend("Manually suspended");
instance.Resume();
waitHandle.WaitOne();
在我的应用程序中,我将WorkflowRuntime作为一个单例实现,因为我发现在创建这样的WorkflowRuntime时存在巨大的内存泄漏。因此,我的代码如下所示:

using(WorkflowRuntimeManager manager = new WorkflowRuntimeManager(new WorkflowRuntime("WorkflowRuntime")))
{
  manager.WorkflowRuntime.StartRuntime();
  WorkflowInstanceWrapper instance = manager.StartWorkflow(typeof(SharedWorkflows.Workflow1), null);
  instance.Suspend("Manually suspended");
  instance.Resume();
  waitHandle.WaitOne();
}
WorkflowInstance instance = WorkflowRuntimeSingleton.Instance.workflow_runtime.CreateWorkflow(typeof(SharedWorkflows.Workflow1), null);
instance.Start();
instance.Suspend("Manually suspended");
instance.Resume();
waitHandle.WaitOne();
现在,如果我像上面所示调用Suspend和Resume,它工作正常。但是如果我通过GUI发出调用,它会抱怨持久性服务

有了这些信息,我不想仅仅为了获得这三个函数而建立一个数据库,我想知道我需要做些什么来实现这一点。在这一点上,我的最佳猜测是WF不喜欢从单独的线程进行控制。如果是这样的话,有没有一种好方法可以让调用看起来好像是从同一个线程发出的

以下是我提出的一些可能的解决方案,但我相信这里的某些人有一种更为奇特和优雅的方式来做到这一点

WF通过GUI接口轮询中止/暂停/恢复似乎真的很蹩脚 将WaitOne替换为WaitAny,并将对拥有工作流的对象的GUI调用设置为AutoResetEvent。WaitAny允许继续执行,然后我的代码可以检查用户按下了哪个按钮。这需要包装在一个循环中,以便我们可以再次等待,直到用户单击Abort,或者直到WF完成。 使用布尔标志基本上执行2正在执行的操作。 查看SO上是否有人知道如何通过正确的线程神奇地拨打电话:
任何见解或意见都将不胜感激

创建持久性数据库没什么大不了的。事实上,这将有助于解决您的内存问题,因为它会持续执行暂停时间超过给定时间段的工作流,从而将其从内存中取出。以下是一个链接,可帮助您创建数据库并在工作流中使用它:

在链接中,它提到更改app.config。不是我干的。相反,我在代码中添加了服务。像这样:

//Add the persistence service
WorkflowPersistenceService persistenceService = new SqlWorkflowPersistenceService(
    DBConnections.PersistenceService,
    true,
    TimeSpan.MaxValue,
    new TimeSpan(0, 0, 15));
m_WorkflowRuntime.AddService(persistenceService);

编辑:

创建持久性数据库没什么大不了的。事实上,这将有助于解决您的内存问题,因为它会持续执行暂停时间超过给定时间段的工作流,从而将其从内存中取出。以下是一个链接,可帮助您创建数据库并在工作流中使用它:

在链接中,它提到更改app.config。不是我干的。相反,我在代码中添加了服务。像这样:

//Add the persistence service
WorkflowPersistenceService persistenceService = new SqlWorkflowPersistenceService(
    DBConnections.PersistenceService,
    true,
    TimeSpan.MaxValue,
    new TimeSpan(0, 0, 15));
m_WorkflowRuntime.AddService(persistenceService);

编辑:

我将此作为答案发布,以便获得适当的格式。我已经按照Gabriel的回答做了,我正在花最宝贵的时间尝试配置数据库。关于这一点,我有几个问题

所有的链接都提到使用MicrosoftSQLServer查询分析器创建数据库,我没有。相反,我转到VS2008中的服务器资源管理器,右键单击数据连接->创建新的SQL Server数据库。我使用Windows身份验证并从服务器列表中选择了我的计算机

我希望能够使用相同的数据库文件在多个系统上运行此代码。为什么我不能在这里指定localhost

关于上面的问题,如果我改为使用数据连接->添加连接创建一个新数据库,我可以创建一个本地数据库文件,我可以将其包含在我的解决方案中,并可能从一台PC移动到另一台PC。这可能是正确的方法,但是

使用Microsoft SQL Server Compact 3.5和Microsoft SQL Server数据库文件之间的主要区别是什么?两者都允许我创建一个文件。我更喜欢Compact选项,因为我不需要使用密码,但我不知道这是否需要在另一台计算机上安装数据库文件选项不需要的其他特殊服务

接下来,我必须执行一个SQL查询来为工作流持久性存储生成表。根据链接页面,此位置为:

%WINDIR%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\<language>\SqlPersistence_Schema
fol 提交人:


有人知道我可以尝试创建持久性存储的其他方法吗?

我将此作为一个答案发布,以便获得适当的格式设置。我已经按照Gabriel的回答做了,我正在花最宝贵的时间尝试配置数据库。关于这一点,我有几个问题

所有的链接都提到使用MicrosoftSQLServer查询分析器创建数据库,我没有。相反,我转到VS2008中的服务器资源管理器,右键单击数据连接->创建新的SQL Server数据库。我使用Windows身份验证并从服务器列表中选择了我的计算机

我希望能够使用相同的数据库文件在多个系统上运行此代码。为什么我不能在这里指定localhost

关于上面的问题,如果我改为使用数据连接->添加连接创建一个新数据库,我可以创建一个本地数据库文件,我可以将其包含在我的解决方案中,并可能从一台PC移动到另一台PC。这可能是正确的方法,但是

使用Microsoft SQL Server Compact 3.5和Microsoft SQL Server数据库文件之间的主要区别是什么?两者都允许我创建一个文件。我更喜欢Compact选项,因为我不需要使用密码,但我不知道这是否需要在另一台计算机上安装数据库文件选项不需要的其他特殊服务

接下来,我必须执行一个SQL查询来为工作流持久性存储生成表。根据链接页面,此位置为:

%WINDIR%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\<language>\SqlPersistence_Schema
其次是:

SQL Execution Error.

Executed SQL statement: -- Copyright (c) Microsoft Corporation. All rights reserved.

SET NOCOUNT ON

--
-- ROLE state_persistence_users
--
declare @localized_string_AddRole_Failed nvarchar(256)
set @localized_string_AddRole_Failed = N'Failed adding the "state_per...
Error Source: .Net SqlClient Data Provider
Error Message: Incorrect syntax near the keyword 'if'.
Incorrect syntax near 'GO'.
Incorrect syntax near the keyword 'CREATE'.
Incorrect syntax near the keyword 'IF'.
Incorrect syntax near 'GO'.
Incorrect syntax near the keyword 'CREATE'.
Incorrect syntax near the keyword 'CREATE'.
Incorrect syntax near the keyword 'DBCC'.
Incorrect syntax near ')'.

有人知道我可以尝试创建持久性存储的其他方法吗?

SQL Server Compact不起作用,因为CE不支持存储过程,存储过程是默认持久性数据库创建脚本的一部分,由SQL持久性服务调用。CE旨在将引擎嵌入到应用程序中。DB文件将与SQLServerExpress一起使用,其中引擎在单独的进程中运行,但您可以指向DBF文件,而不是连接到已连接到引擎的DB


根据您的问题/回答,听起来您不希望使用应用程序的一个实例创建的工作流被另一个实例共享工作流调用。另外一种可能性是不使用持久性服务的SQL版本。有一个示例可能不完整,不确定工作流持久性服务是否基于将工作流直接序列化到位于的文件。我不知道它是否支持您的所有需求,但由于它包含源代码,您可以对其进行调整。

SQL Server Compact不起作用,因为CE不支持存储过程,存储过程是默认持久性数据库创建脚本的一部分,由SQL持久性服务调用。CE旨在将引擎嵌入到应用程序中。DB文件将与SQLServerExpress一起使用,其中引擎在单独的进程中运行,但您可以指向DBF文件,而不是连接到已连接到引擎的DB


根据您的问题/回答,听起来您不希望使用应用程序的一个实例创建的工作流被另一个实例共享工作流调用。另外一种可能性是不使用持久性服务的SQL版本。有一个示例可能不完整,不确定工作流持久性服务是否基于将工作流直接序列化到位于的文件。我不知道它是否支持您的所有需求,但由于它包含源代码,您可以对其进行调整。

我按照说明创建了app.config文件,但随后重新阅读了您的答案,并尝试了代码隐藏方法。DBConnections是如何在你的代码中声明的?@Gabriel:对不起,我很懒,没有深入研究MSDN。我看到它是数据库连接字符串。我必须找出连接到数据库文件的正确字符串。太好了!VS2008实际上在属性选项卡中告诉我数据连接的连接字符串。。。谢天谢地此链接将帮助您创建和使用数据库文件:谢谢!!!我正要手动执行此操作,但现在我不必这样做了我按照描述创建了app.config文件,但随后重新阅读了您的答案,并尝试了您的代码隐藏方法。DBConnections是如何在你的代码中声明的?@Gabriel:对不起,我很懒,没有深入研究MSDN。我看到它是数据库连接字符串。我必须找出连接到数据库文件的正确字符串。太好了!VS2008实际上在属性选项卡中告诉我数据连接的连接字符串。。。谢天谢地此链接将帮助您创建和使用数据库文件:谢谢!!!我正要手动执行此操作,但现在我不必这样做了谢谢,里奇,我想我运气不错,选对了。我正在使用SQL Express处理项目文件夹中的DBF文件。你说得对,我没有使用共享工作流,所以我将研究序列化到fi
乐。最终,这才是我真正想做的。事实上,我根本不想在任何地方坚持下去——我不介意围绕AutoResetEvents和WaitHandles设计一些东西,但WF是我在这个应用程序中开始使用的,我将尝试暂时使用WF方式。非常感谢你的链接。你说你根本不想坚持。除非你的应用程序永远不想暂停工作流、关闭应用程序、重新打开它并恢复工作流,否则你将需要一个持久性服务。谢谢,Rich,我想我很幸运,选择了正确的一个。我正在使用SQL Express处理项目文件夹中的DBF文件。你说得对,我没有使用共享工作流,所以我将研究序列化到文件。最终,这才是我真正想做的。事实上,我根本不想在任何地方坚持下去——我不介意围绕AutoResetEvents和WaitHandles设计一些东西,但WF是我在这个应用程序中开始使用的,我将尝试暂时使用WF方式。非常感谢你的链接。你说你根本不想坚持。除非您的应用程序永远不想暂停工作流、关闭应用程序、重新打开应用程序并恢复工作流,否则您将需要一个持久性服务。