Dot-Net

在 WCF 服務中使用 async/await 時,OperationContext.Current 在第一次等待後為空

  • October 9, 2012

我在 .NET 4.5 中使用 async/await 模式在 WCF 中實現一些服務方法。範例服務:

合同:

[ServiceContract(Namespace = "http://async.test/")]
public interface IAsyncTest
{
   Task DoSomethingAsync();
}

執行:

MyAsyncService : IAsyncTest
{
   public async Task DoSomethingAsync()
   {
       var context = OperationContext.Current; // context is present

       await Task.Delay(10);

       context = OperationContext.Current; // context is null
   }
}

我遇到的問題是第一次await OperationContext.Current返回後null我無法訪問OperationContext.Current.IncomingMessageHeaders.

在這個簡單的範例中,這不是問題,因為我可以在await. 但在現實世界OperationContext.Current中,是從呼叫堆棧的深處訪問的,我真的不想為了進一步傳遞上下文而更改大量程式碼。

有沒有辦法在await不手動將其向下傳遞的情況下獲取操作上下文?

我認為您最好的選擇是實際擷取它並手動傳遞它。您可能會發現這提高了程式碼的可測試性。

也就是說,還有其他幾個選擇:

  1. 將其添加到LogicalCallContext.
  2. 安裝你自己的SynchronizationContext,它會OperationContext.Current在它執行時設置Post;這就是 ASP.NET 保留其HttpContext.Current.
  3. 安裝你自己的TaskScheduler哪套OperationContext.Current

您可能還想在 Microsoft Connect 上提出此問題。

不幸的是,這不起作用,我們將在未來的版本中看到修復。

同時,有一種方法可以將上下文重新應用到目前執行緒,這樣您就不必傳遞對象:

   public async Task<double> Add(double n1, double n2)
   {

       OperationContext ctx = OperationContext.Current;

       await Task.Delay(100);

       using (new OperationContextScope(ctx))
       {
           DoSomethingElse();
       }
       return n1 + n2;
   }  

在上面的範例中,**DoSomethingElse()**方法將按預期訪問 OperationContext.Current。

引用自:https://stackoverflow.com/questions/12797091