【问题标题】:Implementing asynchronous scoping in PCL and Windows Phone applications在 PCL 和 Windows Phone 应用程序中实现异步作用域
【发布时间】:2015-11-21 12:11:38
【问题描述】:

出于某种奇怪的原因,System.Runtime.Remoting.Messaging.CallContextAsyncLocal 类都只能使用完整的 CLR。这使得在使用可移植类库或 Windows Phone 应用程序时进行异步作用域变得非常困难,特别是因为 Windows Phone API 正在变得仅限异步;所以我们真的没有不使用 async/await 的选项。

这实际上意味着在 WPF 或 WinForms 中,我们可以编写如下方法:

private async void button_Click(object sender, EventArgs e)
{
    CallContext.LogicalSetData("x", new object());
    await Something();
    var context = CallContext.LogicalGetData("x");
}

在 WPF 和 WinForms 中,该框架确保每次单击同一个按钮都能获得自己的上下文,并且可以独立运行。使用ThreadLocal<T>[ThreadStatic] 很难达到同样的效果,因为每次点击都会在 UI 线程上执行。

我的问题是,我们将如何在不支持CallContextAsyncLocal<T> 的Windows Phone、Store 和其他应用程序类型中解决这个问题?

一些背景资料:

我们经常希望(业务)逻辑在某种上下文中运行。此上下文可以包含业务逻辑可以在整个操作中使用的信息。在服务器环境中这很容易想象,因为您需要在数据库事务中运行请求,需要访问当前用户、租户 ID 等。但即使在客户端应用程序中,操作也可能需要访问上下文信息,例如当前正在运行的操作或日志上下文的相关 ID。在此类操作期间(例如单击事件),我们可能需要解析其他服务(来自我们的Composition Root)。为了使操作成功运行,我们可能需要在整个客户端操作中重用相同的组件,这意味着我们的 Composition Root 需要了解它正在运行的上下文。

虽然所有这些信息都可以使用服务的公共 API 的方法调用通过整个系统传递,但这不仅会迫使我们用实现细节污染应用程序中服务的 API,还会导致严重的维护问题,因为我们必须在整个系统中传递所有这些信息,并且对我们的一个组件进行简单的内部更改将通过所有方法调用在调用堆栈中传播。当涉及到我们的组合根时,我们绝对不想通过应用程序传递我们的 DI 库的一些缓存/范围对象,因为这会将我们的业务逻辑紧密耦合到外部库。显然,我们也不想传递某种service locator

因此,在客户端应用程序中使用 CallContextAsyncLocal<T> 之类的东西来实现范围非常重要。

【问题讨论】:

    标签: c# .net asynchronous windows-phone


    【解决方案1】:

    抱歉,今天没有简单的解决方案。当 Windows Phone(最终)变为“手机上的 Windows 10”(即,AsyncLocal<T>)时,这将成为可能。但是现在……

    执行此操作的最简单方法是显式(作为参数)或隐式(作为this 上的成员变量)传递上下文。

    也可以使用自定义等待器来实现此功能的有限版本。但除了极其复杂之外,该解决方案还需要您修改整个应用程序中的每个 await(或使用编译后 IL 重写来实现相同的效果)。

    【讨论】:

    • 废话。不是我希望的答案。
    • @Steven:对不起!作为安慰奖,欢迎您相信隐式上下文不是一个伟大的设计。它们非常适合记录上下文(将多个日志消息分组为单个逻辑“活动”),仅此而已。不可见的上下文对于真正的业务数据/逻辑来说是一种糟糕的机制——它们使系统难以测试和维护。我编写了大量异步代码,并且(除了“活动”相关性),我只在调试时使用隐式上下文来创建因果堆栈,从不在生产环境中,当然也从不携带业务层信息。
    • 我同意这对业务逻辑不利,但透明的上下文(如TransactionScope)非​​常适合基础设施问题,它们实际上使开发人员的生活更加轻松。 Simple Injector(一个 DI 库)围绕这个概念设计了范围生活方式,这使开发人员的生活变得更加轻松,因为它允许他们的业务逻辑完全忘记它正在运行的范围。通过 DI 容器的整个系统的范围会导致 DI 容器上的强耦合,这是不好的做法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    相关资源
    最近更新 更多