代码契约和异步

Law*_*eld 17 .net c# code-contracts task-parallel-library async-ctp

将后置条件添加到返回的异步方法的推荐方法是什么Task<T>

我已经阅读了以下建议:

http://social.msdn.microsoft.com/Forums/hu-HU/async/thread/52fc521c-473e-4bb2-a666-6c97a4dd3a39

帖子建议将每个方法实现为同步,签约,然后将异步对应实现为简单的包装器.不幸的是,我不认为这是一个可行的解决方案(也许是通过我自己的误解):

  1. 异步方法虽然被假定为同步方法的包装器,但没有任何真正的代码契约,因此可以按照自己的意愿进行.
  2. 致力于异步的代码库不太可能为所有内容实现同步对应.因此,实现包含await其他异步方法的新方法因此被强制为异步.这些方法本质上是异步的,不能轻易转换为同步.它们不仅仅是包装纸.

即使我们通过说我们可以使用.Result.Wait()代替await(这实际上会导致某些SyncContexts死锁,并且无论如何都必须在异步方法中重写)来使后一点无效,我仍然相信第一点.

有没有其他想法,或者有什么我错过的代码合同和TPL?

Ste*_*ary 14

正如其他人所做的那样,我已经向异步团队指出了这一点.目前,合同和异步(几乎)是互斥的.所以,微软中至少有一些人知道这个问题,但我不知道他们打算怎么做.

我不建议将异步方法编写为同步方法的包装器.事实上,我倾向于做相反的事情.

先决条件可以奏效.我最近没有尝试过; 你可能需要一个包含前置条件的异步方法的小包装器.

后置条件几乎被破坏了.

断言和假设确实正常,但静态检查器确实有限,因为后置条件被破坏了.

不变量在异步世界中没有那么多意义,因为可变状态往往会妨碍它.(Async轻轻地将你从OOP推向一个功能风格).

希望在VS vNext中,Contracts将使用异步感知类型的后置条件进行更新,这也将使静态检查器能够更好地处理异步方法中的断言.

在此期间,您可以通过编写假设来进行假装后置条件:

// Synchronous version for comparison.
public static string Reverse(string s)
{
  Contract.Requires(s != null);
  Contract.Ensures(Contract.Result<string>() != null);

  return ...;
}

// First wrapper takes care of preconditions (synchronously).
public static Task<string> ReverseAsync(string s)
{
  Contract.Requires(s != null);

  return ReverseWithPostconditionAsync(s);
}

// Second wrapper takes care of postconditions (asynchronously).
private static async Task<string> ReverseWithPostconditionAsync(string s)
{
  var result = await ReverseImplAsync(s);

  // Check our "postcondition"
  Contract.Assume(result != null);

  return result;
}

private static async Task<string> ReverseImplAsync(string s)
{
  return ...;
}
Run Code Online (Sandbox Code Playgroud)

代码契约的一些用法是不可能的 - 例如,在接口或基类的异步成员上指定后置条件.

就个人而言,我完全避免使用我的异步代码中的合同,希望微软能在几个月后修复它.

  • @julealgon:不幸的是,没有.我仍然避免使用异步方法的合同.我仍然希望MS能解决这个问题.:) (2认同)