C# - 如何使一系列方法调用原子化?
我必须在 C# 中进行一系列方法调用,这样,如果其中一个失败,则不应调用后续方法。简而言之,这组调用应该是原子的。我如何在 C# 中实现这一目标?
I have to make a sequence of method calls in C# such that, if one of them fails, the subsequent methods should not be called. In short, the set of calls should be made atomic. How do I achieve this in C#?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我认为你将“原子”这个词与其他东西混淆了。原子性是指操作不能被中断,通常在多线程场景中完成以保护共享资源。
您想要的是正常的控制流逻辑,解决方案取决于您的方法。
一种解决方案可能是让它们返回一个布尔值,指示它是否成功:
您还可以使用异常并将所有方法调用包装在 try-catch 块内。如果其中之一失败(抛出异常),您的 catch 块将执行,并且 try 块中的该方法调用之后的任何内容都将没有机会运行。
如果您需要回滚功能,则必须进入事务,但这是一个更大的主题。
I think you're confusing the word "atomic" with something else. Atomic is when an operation cannot be interrupted and is usually done in multi threaded scenarios to protect shared resources.
What you want is normal control flow logic and the solution depends on what your methods looks like.
One solution could be to have them return a boolean indicating whether or not it succeeded:
You could also use exceptions and wrap all your method calls inside a try-catch block. If one of them fails (throws an exception), your catch block will execute and nothing after that method call in the try-block will get a chance to run.
If you need rollback functionality, you have to get into transactions but that's a whole bigger topic.
TransactionScope 可能是您需要的,请参见此处
TransactionScope might be what you need see here
最好让它们在失败时抛出异常,并将您的调用序列写入
try
/catch
块中。如果由于某种原因无法做到这一点,请让它们在成功时返回 true 并使用
&&
:(这不是真正意义上的“原子”这个词,但我不认为你要求真正的原子性。)
Preferably, get them to throw an exception when they fail and write your call sequence in a
try
/catch
block.If you can't do that for some reason, get them to return true on success and use
&&
:(That's not "atomic" in the true sense of the word, but I don't think you're asking for true atomicity.)
这不是原子的意思。正如其他答案所解释的,您可以通过检查每个方法调用的结果并在获得特定结果时停止来实现此目的。
原子意味着要么调用所有方法,要么不调用任何方法。因此,您可以保证整个块运行或根本不运行。这不是你可以用 C# 代码或我所知道的大多数语言实现的。
您需要做的是将检查结果与最终处理分开,并将最终处理排队。
因此,不要:
做类似的事情:
这仍然离真正的“原子”还很远,但它确实给了你一个非常基本的“全有或全无”效果。
That is not what atomic means. As other answers have explained you can achieve this simply by checking the result of each method call and stopping when you get a certain result.
Atomic means that either all of the methods are called or none of them are. So you guarantee that the entire block runs or doesn't run at all. This is not something you can achieve in C# code, or in most languages that I'm aware of.
What you would have to do is separate checking results from final processing and queue up the final processing instead.
So instead of:
Do something like:
This still isn't anywhere's close to being actually "atomic", but it does give you a very basic "all or nothing" effect.
如果您没有捕获异常,那么如果抛出异常,所有其他方法都会调用中止,直到找到
try
块。因此,只需在需要结束原子调用时(例如,当它失败时)抛出一个异常,然后在需要返回正常程序时捕获它。If you are not catching exceptions, then if you throw an exception, all other methods called abort until a
try
block is found. So simply throw an exception where you need to have the atomic calls end (e.g. when it fails) and then catch it when you need to return to normal rutine.这是一个在出现问题时模拟带有补偿的移动操作的粗略示例。设备复制方法失败时抛出异常
或带有错误代码,例如失败时可能为 bool 或检查整数
Here is a rough example of emulating a move operation with compensation if things go wrong. With exceptions thrown from your device copy methods on failure
Or with error codes e.g. could be bool for failed or check an integer
您是否正在考虑多播代表?类似于:
这不起作用,因为调用函数的顺序未定义。另外,由于您的委托函数无法返回值,因此除了抛出异常之外,无法表明它们失败了。如果您要抛出异常,最好使用前面的建议之一,因为这样您的执行顺序就已定义(并且您的方法不必都具有相同的签名)。
Are you thinking of multicast delegates? Something like:
This won't work, because the order that the functions is called in is undefined. Plus, since your delegate functions can't return a value, there's no way to indicate that they failed, except by throwing an exception. And if you're going to throw an exception, you're better off using one of the earlier suggestions, as then your order of execution is defined (and your methods don't all have to have the same signature).