如果这个问题跑题了,您可以在评论中写下稍后删除:)
如果我有一个 3 层 ( *.DLL's )
- DataAccessLayer.DLL
- 业务逻辑层.DLL
- UI 应用程序(WPF、WinForms,任何技术)
在我的应用程序中,我让 BusinessLogicLayer 方法返回 Task,在 UI 应用程序中,当我使用来自 BusinessLogicLayer 的方法时调用 await
我有以下误解:
- Task 或并发性应该支持哪一层(Back-End、Middle-were、Front)
- 如果我需要为其他开发人员制作可重用的 BusinessLogicLayer,他们也可能会忘记在处理给他们的下一个项目中使用 UI 应用程序层中的可等待/异步方法。如何在 Middle 层中实现可等待方法,而无需在每个 UI 事件(例如 Button_Click)中编写 await。
- 如何在不使用await、async关键字的情况下,让DataAccessLayer只包含UI层的并发和等待。
我的简单代码包含以下内容:
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's 关键字和 async。
What i actually do is failed and don't know why this happen
我尝试制作如下场景:
将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
public async void MoveNext() => await EntryBase.MoveNext();
然后从逻辑层调用 UI 层中的 MoveNext。我想这将使它可以等待,因为它已经在 middle-were 层中声明了等待。但实际上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 */ }
如有任何帮助,我们将不胜感激。
最佳答案
What i need to make is get rid off await's keywords and async in UI layer.
这是完全错误的。 UI 层是唯一必须使用 async
和 await
的地方。它们确实必须在该层中使用。
您的数据访问技术未指定,但从代码来看,我猜它可能是基于 DataTable
的,这是有问题的,因为 DataTable
非常古老并且确实不支持异步
。注意 wrapping method bodies with Task.Run
to "make them asynchronous" is an antipattern - 这些实际上是 fake-asynchronous methods ,不是真正的异步。
如果我错了并且您的数据访问技术确实支持async
,那么您应该能够使您的 DAL 方法async
不使用 Task.Run
。从最低 级别开始(例如,FetchDataBuffer
调用的任何方法)并将它们更改为异步等价物。然后让 async
从那里成长。请注意,“让异步增长”意味着使用 async Task
,而不是 async void
; async void
in the BLL is definitely an antipattern .
但是如果我是对的并且您的 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 应用程序之外的使用受到限制。
关于c# - .NET 中的 N 层架构模式中的哪一层应该填充并发和任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55161008/