2014-02-24 200 views
3

我需要同步調用一個異步方法,原因不在我的控制範圍之內。我正在開發一個庫,它使用另一個異步工作的庫,我需要從Stream類的實現中使用它。這些類包含同步和異步方法,並且我感覺不安同步的:同步調用異步方法

public override sealed int Read(byte[] buffer, int offset, int count) 
{ 
    // potential deadlock on single threaded synchronization context 
    return ReadAsync(buffer, offset, count).Result; 
} 

public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) 
{ 
    return await _lib.ReadAsync(buffer,offset,count); 
} 

我一直在閱讀How would I run an async Task<T> method synchronously?,特別this answer,並在評論@Stephen克利裏指出,解決不好,因爲有些ASP.NET部件需要AspNetSynchronizationContext。我正在開發一個圖書館,所以我不知道我的課程將從何處被調用。

什麼是最安全的同步調用異步方法?

回答

3

Stephen Toub covers all the various approaches with their corresponding drawbacks在他的博客上。

只有兩種通用的解決方案,這兩者都不是理想的:

  1. 複製在層中的邏輯;讓你的同步方法調用庫中的同步方法。 (這裏假設庫具有同步方法以及異步)。
  2. 返回的任務上的塊,類似於您的示例代碼。這假定圖書館總是使用ConfigureAwait(false),這是一個你無法控制的假設。如果庫是上下文無關的,那麼將異步調用放入Task.Run並阻止該任務可能更安全。此外,確保在阻止任務時解包異常,因爲WaitResult將在AggregateException中包裝異常。

這兩種解決方案都有一些嚴重的維護問題。

+0

我錯過了什麼嗎? '任務。等待'不管繼續政策如何都會阻止。 – Gusdor

+2

@Gusdor:像我這樣解釋是[導致死鎖的簡單方法](http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html),正如我在我的博客上解釋的。 –

+0

Touché!我錯過了一些東西。感謝您的解釋。 – Gusdor