是否可以在C#5.0中使用相同的异步方法签名,并能够在以后决定如何执行此类方法

Eve*_*req 6 .net c# async-await c#-5.0

我想使用最近的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;

   }
}
Run Code Online (Sandbox Code Playgroud)

现在我将如何使用异步方法(你可以忽略消费者在我的情况下实际上是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);
     }
} 
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我有2个实现,每个实现的执行方式不同:一个我想在异步中运行而不阻塞线程(SomeConcreteProvider2),而另一个我希望能够同步运行并且不创建任何Task对象等(我无法在上面的代码中编码,即我在这里创建新任务!).

有一些问题,如何同步运行异步Task <T>方法?.但是我不希望同步运行某些内容...如果我在代码时(即在运行时之前)知道某些方法实现实际上不会是异步并且不需要使用任何线程/我,我想避免任何开销/ O完成端口等.如果你检查上面的代码,很容易看出SomeConcreteProvider1中的方法基本上会构造一些字符串(html),可以在同一个执行线程上快速完成.然而,SomeConcreteProvider2中的相同方法需要创建Web请求,获取Web响应并进行处理,我确实想在Async中至少制作Web请求,以避免在请求时间内阻塞整个线程(实际上可能会长时间退出).

所以问题是:如何组织我的代码(不同的方法签名或不同的实现,或?),以便能够决定如何执行方法,并避免任何可能的开销,例如由SomeConcreteProvider1中的Task.Run(...)引起的.Process方法?

更新1:明显的解决方案(我在问题过程中考虑其中一些),例如向每个提供者添加一些静态属性(比如'isAsyncImplementation'),然后检查该属性以决定如何运行方法(等待或者没有等待控制器动作)也有一些开销:如果可能,DI想要更好的东西:D

spe*_*der 10

在你的第一个案例中,我建议你回复:

Task.FromResult(result)
Run Code Online (Sandbox Code Playgroud)

它返回一个准备完成的任务.

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

  • @EvereQ - MVC4 beta有一个错误,它无法处理已经完成的任务返回.建议的beta解决方法是在任何此类异步方法的顶部添加Task.Yield,但在此实例中,Task.Run听起来像是一个可行的解决方法. (3认同)