簡體   English   中英

當您只能運行同步時滿足異步接口方法

[英]Satisfying an async interface method when you can only run sync

我正在使用作為 COM+ 對象實現的“API”(我松散地使用該術語)。 據我所知,不支持 COM+ 提供的任何排隊功能,但我對 COM+ 的了解幾乎為零。 把它和一粒鹽一起吃。 我只有一種方法可用: invoke ,它是同步的。

出於個人的聰明才智,我圍繞這個 COM+ 對象創建了一個 Web Api 包裝器,它只有一個端點,使用請求的 post 主體調用 COM+ 對象。 這使我可以改為對 Web Api 進行異步調用(以及從我的應用程序中刪除可怕的依賴項)。

現在,我正在創建一個庫來基本上抽象所有這些混亂,但我決定實現一個提供者模式,您可以選擇直接使用 COM+ 或 Web Api 包裝器。 很明顯,我有一個接口,包含同步和異步方法。 Web Api 提供程序當然沒問題,因為您可以通過任何一種方式執行 HTTP 請求,但是我與 COM+ 提供程序遇到了障礙。 由於異步不是那里的選項。

所以,在我看來,我有三個選擇:

  1. “實現”帶有NotImplementedException的異步接口方法,這違反了接口隔離原則。

  2. 做一些不明智的事情,例如使用Task.Run ,我知道在這種情況下它並不是真正的異步,並且基本上是針對針對我的庫進行編程的任何人。

  3. 做一些事情,比如創建接口的同步和異步版本,從接口隔離的角度來看更好,但從提供者模式的角度來看更糟。 如果我依賴於異步接口,那么 COM+ 提供程序將永遠無法使用,如果我依賴同步接口,那么我將永遠無法使用 Web Api 提供程序的異步方法。

總而言之,我的一般問題是,在需要異步運行某些東西但需要使用的方法只能同步運行的情況下,您會怎么做? 如果沒有真正的替代方案,那么滿足接口要求的最不冒犯性的方法是什么?

編輯

我忘了再提一個選項:

  1. 在異步實現中調用方法同步,然后簡單地返回帶有結果的Task.FromResult 這意味着我不會拉新線程(這可能是 Web 應用程序中的一個問題),但我不確定這是否真的比Task.Run更好, Task.Run它實際上是向消費者撒謊“異步”。

我找到的解決方案是使用Task.FromResult返回一個Task即使沒有進行任何異步操作。 雖然這實際上不是異步的,但它滿足接口。 然后,我對該方法進行了注釋,以指出它將運行同步,並且在無法阻止線程(例如 GUI)的情況下,應將其作為委托傳遞給Task.Run 使用Task.Run並不適用於所有情況(例如 Web 應用程序),它是一個實現細節,應該由庫的使用者決定。

也就是說,要真正實現這一點,您需要處理三個Task場景:完成、故障和取消。 這是執行所有這些操作的實際代碼:

public Task<int> DoSomethingAsync(CancellationToken cancellationToken)  
{
    if (cancellationToken.IsCancellationRequested)
    {
        return Task.FromCanceled<int>(cancellationToken);
    }

    try
    {
        return Task.FromResult<int>(DoSomething());
    }
    catch (Exception e)
    {
        return Task.FromException<int>(e);
    }
}

首先,這可確保操作未被取消。 如果是,則返回已取消的任務。 然后,我們需要做的同步工作被包裹在一個 try..catch 塊中。 如果拋出異常,我們需要返回包含該異常的錯誤任務。 最后,如果它正確完成,我們返回一個已完成的任務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM