架构异步/计谋 [英] Architecture for async/await

查看:99
本文介绍了架构异步/计谋的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果您使用的是异步/等待在你的架构一个较低的水平,是有必要冒泡的异步/计谋调用一路上扬,是低效的,因为你基本上是创建一个新的线程为每一层(异步调用异步函数的每一层,或者它没有真正的问题,是仅仅依赖于你的preference?

我使用的是EF 6.0素α3,这样我可以在EF异步方法。

我的资料库是这样的:

公共类EntityRepository< E> :IRepository< E>其中E:类 {     公共异步虚拟任务保存()     {         等待context.SaveChangesAsync();     } }

现在我的业务层是这样:

公共抽象类ApplicationBCBase< E> :IEntityBC< E> {     公共异步虚拟任务保存()     {         等待repository.Save();     } }

然后当然我在我的UI方法将不得不调用时遵循相同的模式。

是这样的:

  1. 必要
  2. 在负面的性能
  3. 的preference只是一个问题

即使这不是在单独的层中使用/项目,同样的问题适用于如果我要求在同一类的嵌套方式:

专用异步任务<字符串> Dosomething1()     {         //其他的东西         ...         返回等待了doSomething2();     }     私人异步任务<字符串>了doSomething2()     {         //其他的东西         ...         返回等待Dosomething3();     }     私人异步任务<字符串> Dosomething3()     {         //其他的东西         ...         返回等待Task.Run(()=>中);     }

解决方案
  

如果您使用的是异步/等待在你的架构一个较低的水平,是有必要冒泡的异步/计谋调用一路上扬,是低效的,因为你基本上是创造每层一个新的线程(异步调用异步函数的每一层,或者它没有真正的问题,是仅仅依赖于你的preference?

此问题提出了几个误解的地方。

首先,你的的创建一个新线程每次调用异步函数。

其次,你并不需要声明一个异步方法,只是因为你调用一个异步函数。如果你很高兴与这已经返回的任务,只返回从一个方法,它的的有异步修改:

 公共类EntityRepository< E> :IRepository< E>其中E:类
{
    公共虚拟任务保存()
    {
        返回context.SaveChangesAsync();
    }
}

公共抽象类ApplicationBCBase< E> :IEntityBC< E>
{
    公共虚拟任务保存()
    {
        返回repository.Save();
    }
}
 

本的将会的稍微更有效,因为它不涉及一个状态机被很少的原因产生的 - 但更重要的是,它更简单

任何异步方法,你有一个等待 EX pression等待工作任务< T> ,就在该方法没有进一步的处理结束后,将更好写入,而不使用异步/等待。所以这样的:

 公共异步任务<字符串>美孚()
{
    VAR栏=新的酒吧();
    bar.Baz();
    返回等待bar.Quux();
}
 

是更好的写法如下:

 公共任务<字符串>美孚()
{
    VAR栏=新的酒吧();
    bar.Baz();
    返回bar.Quux();
}
 

(理论上存在的任务非常细微的差别被创建,因此来电者可能会增加延续,但在案件的绝大多数,你不会注意到任何区别的。)

If you are using async/await at a lower level in your architecture, is it necessary to "bubble up" the async/await calls all the way up, is it inefficient since you are basically creating a new thread for each layer (asynchronously calling an asynchronous function for each layer, or does it not really matter and is just dependent on your preference?

I'm using EF 6.0-alpha3 so that I can have async methods in EF.

My repository is such:

public class EntityRepository<E> : IRepository<E> where E : class
{
    public async virtual Task Save()
    {
        await context.SaveChangesAsync();
    }
}

Now my business layer is as such:

public abstract class ApplicationBCBase<E> : IEntityBC<E>
{
    public async virtual Task Save()
    {
        await repository.Save();
    }
}

And then of course my method in my UI would have the follow the same pattern when calling.

Is this:

  1. necessary
  2. negative on performance
  3. just a matter of preference

Even if this isn't used in separate layers/projects the same questions applies to if I am calling nested methods in the same class:

    private async Task<string> Dosomething1()
    {
        //other stuff 
        ...
        return await Dosomething2();
    }
    private async Task<string> Dosomething2()
    {
        //other stuff 
        ...
        return await Dosomething3();
    }
    private async Task<string> Dosomething3()
    {
        //other stuff 
        ...
        return await Task.Run(() => "");
    }

解决方案

If you are using async/await at a lower level in your architecture, is it necessary to "bubble up" the async/await calls all the way up, is it inefficient since you are basically creating a new thread for each layer (asynchronously calling an asynchronous function for each layer, or does it not really matter and is just dependent on your preference?

This question suggests a couple of areas of misunderstanding.

Firstly, you don't create a new thread each time you call an asynchronous function.

Secondly, you don't need to declare an async method, just because you're calling an asynchronous function. If you're happy with the task that's already being returned, just return that from a method which doesn't have the async modifier:

public class EntityRepository<E> : IRepository<E> where E : class
{
    public virtual Task Save()
    {
        return context.SaveChangesAsync();
    }
}

public abstract class ApplicationBCBase<E> : IEntityBC<E>
{
    public virtual Task Save()
    {
        return repository.Save();
    }
}

This will be slightly more efficient, as it doesn't involve a state machine being created for very little reason - but more importantly, it's simpler.

Any async method where you have a single await expression awaiting a Task or Task<T>, right at the end of the method with no further processing, would be better off being written without using async/await. So this:

public async Task<string> Foo()
{
    var bar = new Bar();
    bar.Baz();
    return await bar.Quux();
}

is better written as:

public Task<string> Foo()
{
    var bar = new Bar();
    bar.Baz();
    return bar.Quux();
}

(In theory there's a very slight difference in the tasks being created and therefore what callers could add continuations to, but in the vast majority of cases, you won't notice any difference.)

这篇关于架构异步/计谋的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆