3 .net c# task n-tier-architecture async-await
如果这个问题偏离主题,请在评论中写下稍后删除:)
如果我有 3 层(*.DLL)
在我的应用程序中,我使 BusinessLogicLayer 方法返回任务,在 UI 应用程序中,当我使用 BusinessLogicLayer 中的方法时,我调用 wait
我有以下误解:
我的简单代码包含以下内容:
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();
}
Run Code Online (Sandbox Code Playgroud)
BusinessLogicLayer.DLL现在以简单的方式包装了数据访问方法
public Task MoveNext() => Task.Run(() => { EntryBase.MoveNext(); });
Run Code Online (Sandbox Code Playgroud)
UI 层(.NET 中的任何应用程序或前端提供商)
private async void BtnNext_ItemClick(object sender, ClickEventArgs e)
{
await EntryLogic.MoveNext();
DeserializeBuffer();
}
Run Code Online (Sandbox Code Playgroud)
如上所示,在并发方法 ( MoveNext ) 完成之前, DeserializeBuffer方法不会执行。
我需要做的是摆脱UI层中的await关键字和async。
我实际上做的是失败的,不知道为什么会发生这种情况
我尝试制作的场景如下:
将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();
});
}
Run Code Online (Sandbox Code Playgroud)
然后在Middle-weer层BusinessLogicLayer中调用await
公共异步无效MoveNext()=>等待EntryBase.MoveNext();
之后从逻辑层调用UI层中的MoveNext。我想这将使其成为可等待的,因为它已经在中间层声明了等待。但实际上UI层同时执行了next方法。因此抛出的异常是因为下一个方法(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 */
}
Run Code Online (Sandbox Code Playgroud)
任何帮助,将不胜感激。
我需要做的是摆脱UI层中的await关键字和async。
这是完全错误的。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();
}
Run Code Online (Sandbox Code Playgroud)
这不是反模式,因为我们用来Task.Run调用一个方法 - 将其移出 UI 线程。这并不理想,因为我们仍然使用了超出必要数量的线程,但理想的解决方案需要真正的异步数据访问。通过这种妥协,您的 DAL 和 BLL 仍然处于阻塞状态,因此它们在桌面 UI 应用程序之外的使用受到限制。