Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何实现返回任务的接口方法<;T>;?_C#_.net_Asynchronous_Task Parallel Library_Async Await - Fatal编程技术网

C# 如何实现返回任务的接口方法<;T>;?

C# 如何实现返回任务的接口方法<;T>;?,c#,.net,asynchronous,task-parallel-library,async-await,C#,.net,Asynchronous,Task Parallel Library,Async Await,我有一个接口 interface IFoo { Task<Bar> CreateBarAsync(); } 但是我应该如何实现类Foo2,该类使用同步方法来创建Bar 我可以实现同步运行的方法: async Task<Bar> CreateBarAsync() { return SynchronousBarCreator(); } 从性能的角度来看,我认为两种方法的开销大致相同,或者 我应该选择哪种方法;同步地实现async方法,或者显式地将同

我有一个接口

interface IFoo
{
  Task<Bar> CreateBarAsync();
}
但是我应该如何实现类
Foo2
,该类使用同步方法来创建
Bar

我可以实现同步运行的方法:

  async Task<Bar> CreateBarAsync()
  {
    return SynchronousBarCreator();
  }
从性能的角度来看,我认为两种方法的开销大致相同,或者

我应该选择哪种方法;同步地实现
async
方法,或者显式地将同步方法调用包装到
任务中

编辑

我正在处理的项目实际上是一个.NET4项目,具有来自NuGet包的异步/等待扩展。在.NET4上,
Task.Run
可以替换为
TaskEx.Run
。我有意识地在上面的例子中使用了.NET 4.5方法,希望使主要问题更加清楚。

试试这个:

class Foo2 : IFoo
{
    public Task<Bar> CreateBarAsync()
    {
        return Task.FromResult<Bar>(SynchronousBarCreator());
    }
}
class Foo2:IFoo
{
公共任务CreateBarAsync()
{
返回Task.FromResult(SynchronousBarCreator());
}
}

使用提供的值创建指定类型的已完成任务。

如果使用.NET 4.0,则可以使用
TaskCompletionSource

Task CreateBarAsync()
{
var tcs=new TaskCompletionSource();
SetResult(SynchronousBarCreator());
返回tcs.Task
}

最终,如果您的方法没有什么异步的话,您应该考虑暴露一个同步端点(<代码> CREATABAR < /代码>),它创建了一个新的<代码>栏<代码>。这样就不会有任何意外,也不需要使用冗余的

任务

当您必须从接口实现异步方法并且实现是同步的时,您可以使用Ned的解决方案:

public Task<Bar> CreateBarAsync()
{
    return Task.FromResult<Bar>(SynchronousBarCreator());
}
public任务CreateBarAsync()
{
返回Task.FromResult(SynchronousBarCreator());
}
使用此解决方案,该方法看起来是异步的,但却是同步的

或者您提出的解决方案:

  Task<Bar> CreateBarAsync()
  {
    return Task.Run(() => SynchronousBarCreator());
  }
Task CreateBarAsync()
{
返回任务。运行(()=>SynchronousBarCreator());
}
这样,该方法是真正异步的


您没有一个通用的解决方案可以匹配“如何实现返回任务的接口方法”的所有情况。这取决于上下文:您的实现是否足够快,因此在另一个线程上调用它是无用的?调用此方法时如何使用此接口(它会冻结应用程序)?甚至可以在另一个线程中调用您的实现吗?

为了补充其他答案,还有一个选项,我相信它也适用于.NET 4.0:

class Foo2 : IFoo
{
    public Task<Bar> CreateBarAsync()
    {
        var task = new Task<Bar>(() => SynchronousBarCreator());
        task.RunSynchronously();
        return task;
    }
}


在这种情况下,我相信
Task.FromResult(SynchronousBarCreator())
Task.Run(…)
更好,因为它实际上并没有计划和运行任务来获得结果。
SynchronousBarCreator
是否长期运行?它是CPU受限,还是花时间等待其他东西?在我现在正在处理的情况下,它不会长时间运行。但在未来的场景中可能会出现这种情况。这非常令人困惑,而且不是最佳实践。我的建议是:创建一个同时具有同步和异步方法的接口。这种方法的一个很好的例子是WebClient、EF等,。。。或者创建两个接口,一个用于同步,另一个用于异步方法。非常感谢,Ned,对于我的场景来说,这似乎是一个非常好的解决方案。我还在寻找一个可以在.NET4上使用异步扩展的解决方案,幸运的是,
TaskEx
类还包含一个
FromResult
方法。总而言之,我对这个解决方案非常满意。很高兴我能帮助大家。嘿,为什么你会给这个答案打分?此方法同步运行,但具有异步后缀并返回任务,这一点都不正确。您应该返回Task.Run(SynchronousBarCreator)以使其异步。+1为了支持此答案,我检查了Microsoft对其
MemoryStream.ReadAsync所做的操作,这正是他们所使用的。看见把它添加到你已经很好的答案中可能会很有用:)非常感谢,尤瓦尔,也很高兴知道。如果没有来自Microsoft async NuGet包的异步扩展,这甚至可以工作,对吗?然而,我确实在.NET 4项目中包含了异步扩展,然后,
TaskEx.FromResult
方法似乎是更吸引人的方法。是的,您可以使用它而无需任何扩展
Task.FromResult
TaskEx.FromResult
只是
TaskCompletionSource
的一个包装,可以链接
任务。运行
(或等待任务。延迟,或使用ContinueWith),如果这个方法将来是异步的-现在不异步执行它可能会创建不可预知的执行顺序或导致竞争条件。您是否会推荐我的第一个实现(
async Task CreateBarAsync(){return SynchronousBarCreator();}
),或者这种方法永远不可取?您不应该使用
任务。Run
几乎总是被过度使用。真正使用它的原因只有一个,那就是当您在GUI应用程序上进行计算时。但是很少有计算(相对于CPU)密集型任务。@Aron我同意它经常被过度使用。当您必须调用同步的第三方库时,即使它执行本可以异步完成的耗时任务,它也会很有用。非常高兴知道,非常感谢您提供这些附加信息!如果在等待异步方法之前抛出异常,则该异常将被抛出到同一堆栈上或同时存储?@Guillaume,是的,该异常也将被存储,即使是从
async
方法的同步部分抛出。
public Task<Bar> CreateBarAsync()
{
    return Task.FromResult<Bar>(SynchronousBarCreator());
}
  Task<Bar> CreateBarAsync()
  {
    return Task.Run(() => SynchronousBarCreator());
  }
class Foo2 : IFoo
{
    public Task<Bar> CreateBarAsync()
    {
        var task = new Task<Bar>(() => SynchronousBarCreator());
        task.RunSynchronously();
        return task;
    }
}
interface IFoo
{
    Task<Bar> CreateBarAsync(CancellationToken token);
}

class Foo2 : IFoo
{
    public Task<Bar> CreateBarAsync(CancellationToken token)
    {
        var task = new Task<Bar>(() => SynchronousBarCreator(), token);
        task.RunSynchronously();
        return task;
    }
}