Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在PCL和Windows Phone应用程序中实现异步作用域_C#_.net_Asynchronous_Windows Phone - Fatal编程技术网

C# 在PCL和Windows Phone应用程序中实现异步作用域

C# 在PCL和Windows Phone应用程序中实现异步作用域,c#,.net,asynchronous,windows-phone,C#,.net,Asynchronous,Windows Phone,出于某种奇怪的原因,和类都只能使用完整的CLR。这使得在使用可移植类库或Windows Phone应用程序时很难进行异步作用域,特别是因为Windows Phone API正变得只异步;因此,我们没有选择不使用async/await 这实际上意味着,在WPF或WinForms中,我们可以编写如下方法: private async void button_Click(object sender, EventArgs e) { CallContext.LogicalSetData("x",

出于某种奇怪的原因,和类都只能使用完整的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
[ThreadStatic]
很难达到同样的效果,因为每次单击都会在UI线程上执行

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

一些背景资料:

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

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


因此,在客户端应用程序中,使用
CallContext
asynchlocal
之类的工具实现作用域是非常重要的。

很抱歉,目前还没有简单的解决方案。当Windows Phone(最终)成为“手机上的Windows 10”(即使用
AsyncLocal
)时,这将是可能的。但是现在

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


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

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