是否可以在 C# 5.0 中使用相同的异步方法签名,并能够在以后决定如何执行此类方法
本文关键字:决定 何执行 类方法 执行 异步方法 是否 | 更新日期: 2023-09-27 18:34:05
我想使用最近的 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 应用程序的事实......它可以是任何东西(:
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 对象等(我无法在上面的代码中编码,即我确实在这里创建新任务!
已经有问题了,例如我将如何同步运行异步任务
所以问题是:如何组织我的代码(不同的方法签名或不同的实现,或者?(以便能够决定如何执行方法并避免任何可能的开销,例如由SomeConcreteProvider1.Process方法中的Task.Run(...(引起的?
更新1:明显的解决方案(我在问题过程中想到了其中一些(,例如向每个提供程序添加一些静态属性(例如"isAsyncImplementation"(,然后检查该属性以决定如何运行方法(在控制器操作中使用await或不使用await(也有一些开销:D如果可能的话,我想要更好的东西:D
在第一种情况下,我建议返回:
Task.FromResult(result)
返回一个现成的任务。
http://msdn.microsoft.com/en-us/library/hh194922%28v=vs.110%29.aspx
你的设计看起来不错。
对于SomeConcreteProvider1
情况,您可以使用 TaskCompletionSource
这将返回一个Task
,而不需要并发。
此外,在使用者代码中,如果Task
已经完成,await
将不会产生。这称为"快速路径",并有效地使方法同步。