gpt4 book ai didi

c# - 使用 async/await 进行设计——一切都应该是异步的吗?

转载 作者:可可西里 更新时间:2023-11-01 03:00:10 25 4
gpt4 key购买 nike

假设我有一个接口(interface)方法实现为

public void DoSomething(User user) 
{
if (user.Gold > 1000) ChatManager.Send(user, "You are rich: " + user.Gold);
}

一段时间后我意识到我想改变它:

public async Task DoSomething(User user) 
{
if (user.Gold > 1000) ChatManager.Send(user, "You are rich: " + user.Gold);
if (!user.HasReward)
{
using(var dbConnection = await DbPool.OpenConnectionAsync())
{
await dbConnection.Update(user, u =>
{
u.HasReward = true;
u.Gold += 1000;
});
}
}
}

我正在更改接口(interface)中的方法签名。但是调用方法是同步的,我不仅要让它们异步,还要让整个调用树异步。

例子:

void A()
{
_peer.SendResponse("Ping: " + _x.B());
}

double X.B()
{
return _someCollection.Where(item => y.C(item)).Average();
}


bool Y.C(int item)
{
// ...
_z.DoSomething();
return _state.IsCorrect;
}

应该改为

async void AAsync()
{
_peer.SendResponse("Ping: " + await _x.BAsync());
}

async Task<double> X.BAsync()
{
// await thing breaks LINQ!
var els = new List<int>();
foreach (var el in _someCollection)
{
if (await y.CAsync(item)) els.Add(el);
}
return _els.Average();
}


async Task<bool> Y.CAsync(int item)
{
// ...
await _z.DoSomething();
return _state.IsCorrect;
}

受影响的调用树可能非常大(许多系统和接口(interface)),因此很难进行此更改。

此外,当第一个 A 方法从接口(interface)方法调用时,如 IDisposable.Dispose - 我无法使其异步。

另一个例子:假设对 A 的多次调用被存储为委托(delegate)。以前它们只是用 _combinedDelegate.Invoke() 调用,但现在我应该通过 GetInvocationList()await 处理每个项目。

哦,还可以考虑用异步方法替换属性 getter。

我不能使用 Task.Wait().Result 因为:

  1. 它正在浪费服务器应用程序中的 ThreadPool 个线程
  2. 它会导致死锁:如果所有 ThreadPool 线程都在等待,则没有线程可以完成任何任务。

所以问题是:即使我不打算在内部调用任何异步方法,我是否应该让我所有的方法一开始都是async?不会影响性能吗?或者如何设计事物以避免这种艰难的重构?

最佳答案

should I make absolutely all my methods initially async even if I'm not planning to call anything async inside?

async 的这个设计问题与 IDisposable 的问题本质上是一样的。也就是说,接口(interface)预测它们的实现。无论您做什么,这都会变得一团糟。

根据我的经验,考虑一个方法/接口(interface)/类并预测它是否会使用 I/O 通常是相当简单的。如果它需要 I/O,那么它应该是任务返回的。有时(但不总是),可以构建您的代码,以便在其自己的代码部分完成 I/O,从而使业务对象和逻辑严格同步。 JavaScript 世界中的 Redux 模式就是一个很好的例子。

但归根结底,有时您会做出错误的决定而不得不进行重构。我认为这比仅仅使 every 方法异步要好得多。您是否让每个 接口(interface)都继承自IDisposable 并在所有地方使用using?不,你只在必要时添加它;并且您应该对 async 采取相同的方法。

关于c# - 使用 async/await 进行设计——一切都应该是异步的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39321306/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com