1

全部,

我查看了对话和对话范围领域的 Castle Active Record 项目(在 .net 中)的源代码。我得出的结论是,活动记录中的对话不能跨越不同的线程。换句话说,当我在线程 A 上创建对话,而不是尝试在线程 B 上使用 ConversationalScope(使用在线程 A 上创建的当前对话)时,我访问例如在线程 AI 上加载的实例上的惰性集合将得到异常因为检查当前线程范围的 SesessionFactoryHolder 将找不到线程 B 的任何注册范围,因为线程范围(在 Windows 形式中)是按线程存储的(线程静态字段)。

上述理解正确吗?如果是,那不是限制吗?对话应该能够跨越不同的线程。如果这是真的,我想请教一些想法,如何在不编写大量代码的情况下跨多个线程共享休眠会话(使用 Castle Active Record)。

编辑:我想在这篇文章中补充一下我的最新发现。上面关于对话不跨越线程的说法仍然成立。关于无法在另一个线程上加载惰性集合的说法是错误的。可以在另一个线程上延迟加载惰性集合(在此示例中为线程 B)。我发现这样做的原因是,只要对话存在,会话就会存在,因此可以访问惰性集合。

编辑2:我想通了。我将在旧帖子中留下这个答案,以便其他对此主题有疑问的人可以受益。

解答: 在城堡活动记录框架中,对话可以跨线程共享。发生的情况是,在新线程上,会话范围始终使用以下行注册:

ConversationalScope 范围 = 新的 ConversationalScope(currConv)

因此,当前线程具有有效的会话范围。然后 SessionFactoryHolder 被迫使用线程的当前会话范围(而不是使用其本地会话)。检索休眠会话的逻辑是将这个任务委托给会话,该会话将返回最后一个休眠会话(在前一个线程 A 上创建)。因此,如果会话范围有效(未释放),您将获得由另一个线程创建的相同会话。

这是示例代码:

线程 A:

IScopeConversation conv = new ScopedConversation();
变种顺序=空;

使用 (ConversationalScope 范围 = 新的 ConversationalScope(conv))
{
  订单 = Order.Load(1);
}

// 生成/运行线程 B,按顺序访问惰性集合

线程 B:

使用 (ConversationalScope 范围 = 新的 ConversationalScope(conv))
{
 IList orderDetails = order.Details; // 不会导致异常,因为对话仍然有效(尚未处理)
}

4

1 回答 1

1

在城堡活动记录框架中,对话可以跨线程共享。发生的情况是,在新线程上,会话范围始终使用以下行注册:

ConversationalScope 范围 = 新的 ConversationalScope(currConv)

因此,当前线程具有有效的会话范围。然后 SessionFactoryHolder 被迫使用线程的当前会话范围(而不是使用其本地会话)。检索休眠会话的逻辑是将这个任务委托给会话,该会话将返回最后一个休眠会话(在前一个线程 A 上创建)。因此,如果会话范围有效(未释放),您将获得由另一个线程创建的相同会话。

于 2012-01-03T17:35:43.863 回答