簡體   English   中英

是否可以在C#5.0中使用相同的異步方法簽名,並能夠在以后決定如何執行此類方法

[英]Is it possible to use same async method signature in C# 5.0 and be able to decide later how to execute such method

我想使用最近的C#5.0異步方法,但是有一些特定的方法。

請考慮以下示例代碼:

public abstract class SomeBaseProvider : ISomeProvider
{
   public abstract Task<string> Process(SomeParameters parameters);    
}

public class SomeConcreteProvider1 : SomeBaseProvider 
{

   // in this method I want to minimize any overhead to create / run Task
   // NOTE: I remove here async from method signature, because basically I want to run 
   // method to run in sync!
   public override Task<string> Process(SomeParameters parameters) {

      string result = "string which I don't need any async code to get";

      return Task.Run(() => result);
   }
}

public class SomeConcreteProvider2 : SomeBaseProvider 
{

   // in this method, it's OK for me to use async / await 
   public async override Task<string> Process(SomeParameters parameters) {

      var data = await new WebClient().DownloadDataTaskAsync(urlToRequest);

      string result = // ... here we convert data byte[] to string some way

      return result;

   }
}

現在我將如何使用異步方法(你可以忽略消費者在我的情況下實際上是ASP.NET MVC4 app的事實......它可以是任何東西):

public class SomeAsyncController : AsyncController
{

    public async Task<ActionResult> SomethingAsync(string providerId)
    {
       // we just get here one of providers I define above
       var provider = SomeService.GetProvider(providerId);

       // we try to execute here Process method in async. 
       // However we might want to actually do it in sync instead, if  
       // provider is actually SomeConcreteProvider1 object.
       string result = await provider.Process(new SomeParameters(...));

       return Content(result);
     }
} 

正如您所看到的,我有2個實現,每個實現的執行方式不同:一個我想在異步中運行而不阻塞線程(SomeConcreteProvider2),而另一個我希望能夠同步運行並且不創建任何Task對象等(我無法在上面的代碼中編碼,即我在這里創建新任務!)。

有一些問題, 如何同步運行異步Task <T>方法? 但是我不希望同步運行某些內容...如果我在代碼時(即在運行時之前)知道某些方法實現實際上不會是異步並且不需要使用任何線程/我,我想避免任何開銷/ O完成端口等。如果你檢查上面的代碼,很容易看出SomeConcreteProvider1中的方法基本上會構造一些字符串(html),可以在同一個執行線程上快速完成。 然而,SomeConcreteProvider2中的相同方法需要創建Web請求,獲取Web響應並進行處理,我確實想在Async中至少創建Web請求以避免在請求時間內阻塞整個線程(實際上可能會長時間退出)。

所以問題是:如何組織我的代碼(不同的方法簽名或不同的實現,或?),以便能夠決定如何執行方法,並避免任何可能的開銷,例如由SomeConcreteProvider1中的Task.Run(...)引起的.Process方法?

更新1 :明顯的解決方案(我在問題過程中考慮其中一些),例如向每個提供者添加一些靜態屬性(比如'isAsyncImplementation'),然后檢查該屬性以決定如何運行方法(等待或者沒有等待控制器動作)也有一些開銷:如果可能,DI想要更好的東西:D

在你的第一個案例中,我建議你回復:

Task.FromResult(result)

它返回一個准備完成的任務。

http://msdn.microsoft.com/en-us/library/hh194922%28v=vs.110%29.aspx

你的設計很好看。

對於SomeConcreteProvider1案例,您可以使用TaskCompletionSource

這將返回一個Task而不需要並發。

此外,在使用者代碼中,如果Task已經完成,則await將不會產生。 這被稱為“快速路徑”並有效地使該方法同步。

暫無
暫無

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

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