用于发布的FireAndForget和Async行为之间的差异

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用于发布的FireAndForget和Async行为之间的差异相关的知识,希望对你有一定的参考价值。

目前,我们正在使用StackExchange.Redis,因为它没有提供“阻止弹出窗口”,我们按照文档中的建议进行操作:

db.ListLeftPush(key, newWork, flags: CommandFlags.FireAndForget);
sub.Publish(channel, "");

这与以下有什么不同?

db.ListLeftPushAsync(key, newWork);
sub.Publish(channel, "");

我们知道命令的目的,我们想知道的是内部是否存在任何差异,或者表现出不同的行为风险? (执行令等)

答案

比较fire和forget与调用异步操作而不是等待它有一个主要区别。

火与遗忘意味着你不仅没有等待结果,而且你不关心它是否有效,而异步操作一旦出现问题就可能抛出异常。

另一方面,当您发出fire和forget命令时,StackExchange.Redis不会尝试在内部检索命令结果,如果您只是想在发出命令时想要所谓的fire and forget行为,那就更好了。

如果打开ConnectionMultiplexer源代码,您可以查看ExecuteAsyncImpl / ExecuteSyncImpl方法是如何实现的,可以检查这种差异:

// For example, ExecuteAsyncImpl...
if (message.IsFireAndForget)
{
  TryPushMessageToBridge(message, processor, null, ref server);
  return CompletedTask<T>.Default(null); // F+F explicitly does not get async-state
}
else
{
  var tcs = TaskSource.CreateDenyExecSync<T>(state);
  var source = ResultBox<T>.Get(tcs);
  if (!TryPushMessageToBridge(message, processor, source, ref server))
  {
    ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(IncludeDetailInExceptions, message.Command, message, server));
  }

  return tcs.Task;
} 

回答一些OP评论

你好。感谢您的回答。我们知道命令的目的,我们想知道的是内部是否存在任何差异,或者是否有任何不同的行为风险(执行顺序等)

由于在Redis通道上发布消息时无法完成异步操作,因此您可能会发布消息并且操作永远不会执行。你失去了很多控制权。

当您发送fire and forget命令时,它可能也不会被执行,但您知道在发布频道消息之前已完成尝试。因此,在使用StackExchange.Redis时,不应使用异步操作来实现fire和forget模式。

您可以查看其他相关的问答:Stackexchange.redis does fire and forget guarantees delivery?

以上是关于用于发布的FireAndForget和Async行为之间的差异的主要内容,如果未能解决你的问题,请参考以下文章

异步/等待有/无等待(即发即弃)

等待一个无效的异步方法

python异步(Async)编程

TAP 和 async/await 是不是意味着用于专用线程?

async=true 用于 css 链接标签

JS async和await关键字