哪个层应该在 .NET 中的 N 层架构模式中填充并发和任务

如果这个问题离题,您可以在评论中写下稍后将其删除:)

如果我有 3 层(*.DLL 的)

  • 数据访问层.DLL

  • 业务逻辑层.DLL

  • UI 应用程序(WPF、WinForms、任何技术)

在我的应用程序中,我让 BusinessLogicLayer 方法返回Task,在 UI 应用程序中,当我使用来自 BusinessLogicLayer 的方法时,我调用 await

我有以下误解:

  • Task 或并发应该支持哪一层(Back-End、Middle-were、Front)

  • 如果我需要为其他开发人员制作可重用的 BusinessLogicLayer,他们也可能忘记在处理他们的下一个项目中使用 UI 应用程序层中的等待/异步方法。如何在中间层实现等待方法,无需在每个 UI 事件(例如 Button_Click)中编写等待。

  • 如何使 DataAccessLayer 只包含并发和在 UI 层中等待,而不需要使用awaitasync关键字。

我的简单代码包含以下内容:

DataAccessLayer.DLL单一方法

public void MoveNext()

{

    if (RecordCount == 0) return;

    Tables[0].Query.Criteria.Clear();

    Tables[0].Query.Sorting = $"ORDER BY {string.Join(" ASC, ", 

    Tables[0].Keys.Select(x => x.KeyID))} ASC";

    FetchDataBuffer();

}

BusinessLogicLayer.DLL现在以简单的方式包装了数据访问的方法


public Task MoveNext() => Task.Run(() => { EntryBase.MoveNext(); });

UI 层(.NET 中的任何应用程序或前端提供程序)


 private async void BtnNext_ItemClick(object sender, ClickEventArgs e)

 {

    await EntryLogic.MoveNext();

    DeserializeBuffer();

 }

如上所示,在并发方法 ( MoveNext ) 完成之前, DeserializeBuffer方法不会执行。


我需要做的是摆脱UI 层中的 await关键字和异步。


我实际上做的是失败,不知道为什么会这样


我尝试制作的场景如下:


将 DataAccessLayer 的方法类型从void转换为Task


   public Task MoveNext()

   {

      return Task.Run(() => { 

      if (RecordCount == 0) return;

      Tables[0].Query.Criteria.Clear();

      Tables[0].Query.Sorting = $"ORDER BY {string.Join(" ASC, ", 

      Tables[0].Keys.Select(x => x.KeyID))} ASC";

      FetchDataBuffer();

      });

     }

然后在中间层BusinessLogicLayer中调用await


公共异步无效 MoveNext() => 等待 EntryBase.MoveNext();


之后从逻辑层调用 UI 层中的 MoveNext。我想这会使它可以等待,因为它已经在中间层声明了等待。但实际上 UI 层同时执行下一个方法。所以抛出的异常是因为关闭下一个方法(DeserializeBuffer)取决于上一个方法(EntryLogic.MoveNext)


  private async void BtnNext_ItemClick(object sender, ClickEventArgs e)

  {

    EntryLogic.MoveNext();

    DeserializeBuffer();  // exception thrown   

     /* because EntryLogic.MoveNext 

     is still executing and not awaited */

  }

任何帮助,将不胜感激。


哈士奇WWW
浏览 118回答 1
1回答

qq_花开花谢_0

我需要做的是摆脱 UI 层中的 await 关键字和异步。这是完全错误的。UI 层是唯一必须async使用的地方。而且它们确实必须在该层中使用。await您的数据访问技术未指定,但从代码来看,我猜它可能是DataTable基于 - 的,这是有问题的,因为DataTable它非常旧并且不支持async. 请注意,使用“使它们异步”包装方法主体Task.Run是一种反模式- 这些实际上是伪异步方法,而不是真正的异步。如果我错了并且您的数据访问技术确实支持async,那么您应该能够在async不使用Task.Run. 从最低级别开始(例如,FetchDataBuffer调用任何方法)并将它们更改为异步等效项。然后让async从那里成长。请注意,“让异步增长”意味着使用async Task,而不是async void; async void在 BLL 中绝对是一种反模式。但是,如果我是对的并且您的 DAL 正在使用DataTable,那么您需要决定是否切换到更新的数据访问技术。如果这不是您现在可以做的事情,那么我建议保留现有的 DAL 和 BLL 代码,并将async/添加await到 UI 层:private async void BtnNext_ItemClick(object sender, ClickEventArgs e){  await Task.Run(() => EntryLogic.MoveNext());  DeserializeBuffer();}这不是反模式,因为我们使用Task.Run的是调用方法——将其移出 UI 线程。这并不理想,因为我们仍在使用比必要更多的线程,但理想的解决方案需要真正的异步数据访问。通过这种妥协,您的 DAL 和 BLL 仍然处于阻塞状态,因此它们在桌面 UI 应用程序之外的使用受到限制。
打开App,查看更多内容
随时随地看视频慕课网APP