异步和等待 - 处理对同一方法的多次调用 - 相互锁定/等待?

2024-01-08

我有一个复杂的基于任务/锁的混乱来执行“长”数据操作,并且我正在尝试用异步/等待替换它。我是异步等待的新手,所以我担心我犯了一些大错误。

为了简化事情,我的 UI 有几个页面依赖于相同的数据。现在,我只需要获取这些数据一次。所以我缓存它,进一步的调用只是从缓存“CachedDataObjects”中获取它,而不是每次都进行长调用。

像这样(半伪代码):

    private Dictionary<Guid,List<Data>> CachedDataObjects;

    public async Task<List<Data>> GetData(Guid ID)
    {
        List<Data> data = null;

        //see if we have any cached
        CachedDataObjects.TryGetValue(ID, out data);

        if (data == null)
        {
            if (ConnectedToServer)
            {
                data = new List<Data>();
                await Task.Run(() =>
                {
                    try
                    {
                        //long data call
                        data = Service.GetKPI(ID);
                    }
                    catch (Exception e)
                    {
                        //deal with errors (passes an action to do if resolved)
                        PromptForConnection(new Task(async () => { data = await GetData(ID); }), e);
                    }
                });
            }

            CachedDataObjects.Add(ID, data);
        }
        return data;
    }

但是,根据异步调用的性质,两个页面在触发时都会调用此方法。

因此,出现了异常 - 具有该 ID 的项目已添加到字典中。即使我修复了这个问题,根本问题仍然存在。数据对象将是不同的版本,我正在进行两次网络调用,而我应该只有一个等等。

以前,我通过将整个方法封装在一个锁定语句中来“破解”一个解决方案 - 从而只允许对其进行一次调用。我的所有数据加载都是在后台工作人员中完成的,第一个执行调用,一旦完成,其他工作人员就会解锁以执行快速抓取。

但我不能在异步方法中使用锁,并且该解决方案无论如何感觉都不好。

有没有办法使用异步方法来“等待”其他异步调用完成?


你的问题是你await在将任务添加到字典之前先对其进行编辑。在这种情况下,您需要添加task到字典中,这样下一个调用此方法的页面将得到相同的结果task:

public Task<List<Data>> GetData(Guid ID)
{
  Task<List<Data>> task = null;
  CachedDataObjects.TryGetValue(ID, out task);
  if (task == null)
  {
    if (ConnectedToServer)
    {
      task = Task.Run(() =>
      {
        try
        {
          //long data call
          return Service.GetKPI(ID);
        }
        catch (Exception e)
        {
          //deal with errors
        }
      });
    }
    DataObjects.Add(ID, task);
  }
  return task;
}

这将缓存task。然而,如果//deal with errors传播异常,那么这也将缓存该异常。

为了避免这种情况,你可以使用更复杂的代码,或者你可以采用我的AsyncLazy<T> type https://github.com/StephenCleary/AsyncEx.Coordination:

private readonly ConcurrentDictionary<Guid, AsyncLazy<List<Data>>> CachedDataObjects;
public Task<List<Data>> GetData(Guid ID)
{
  var lazy = CachedDataObjects.GetOrAdd(ID, id =>
      new AsyncLazy<List<Data>>(() => Task.Run(() =>
      {
        try
        {
          return Service.GetKPI(ID);
        }
        catch (Exception e)
        {
          //deal with errors
          throw;
        }
      }, AsyncLazyFlags.RetryOnFailure | AsyncLazyFlags.ExecuteOnCallingThread)));
  return lazy.Task;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

异步和等待 - 处理对同一方法的多次调用 - 相互锁定/等待? 的相关文章

  • 进程何时获得 SIGABRT(信号 6)?

    C 中进程获得 SIGABRT 的场景有哪些 该信号是否始终来自进程内部 或者该信号可以从一个进程发送到另一个进程吗 有没有办法识别哪个进程正在发送该信号 abort 向调用进程发送SIGABRT信号 就是这样abort 基本上有效 abo
  • ASP.NET MVC 中的经典 ASP (C#)

    我有一个应用程序想要 最终 转换为 ASP NET MVC 我想要进行全面的服务升级 到 ASP NET 但想要使用当前的 ASP 内容来运行当前的功能 这样我就可以在对新框架进行增量升级的同时升级小部分 该站点严重依赖于不太成熟的 VB6
  • asp.net 文本框文本模式数字,仅允许数字

    我只是想知道 ASP NET 中是否有一种方法只允许文本框中的数字textmode number 当我使用这个时
  • C#动态支持吗?

    看完之后这个帖子 https stackoverflow com questions 2674906 when should one use dynamic keyword in c sharp 4 0k和链接 我还有 2 个问题 问题 1
  • 对齐 GridView 中的行值

    我需要在 asp net 3 5 中右对齐 gridview 列中的值 我怎样才能做到这一点
  • POCO HTTPSClientSession 发送请求时遇到问题 - 证书验证失败

    我正在尝试使用 POCO 库编写一个向服务器发出 HTTPS 请求的程序 出于测试目的 我正在连接到具有自签名证书的服务器 并且我希望允许客户端进行连接 为了允许这种情况发生 我尝试安装InvalidCertificateHandler这是
  • 暂停下载线程

    我正在用 C 编写一个非常简单的批量下载程序 该程序读取要下载的 URL 的 txt 文件 我已经设置了一个全局线程和委托来更新 GUI 按下 开始 按钮即可创建并启动该线程 我想要做的是有一个 暂停 按钮 使我能够暂停下载 直到点击 恢复
  • 访问者和模板化虚拟方法

    在一个典型的实现中Visitor模式 该类必须考虑基类的所有变体 后代 在许多情况下 访问者中的相同方法内容应用于不同的方法 在这种情况下 模板化的虚拟方法是理想的选择 但目前这是不允许的 那么 模板化方法可以用来解析父类的虚方法吗 鉴于
  • 如何从 C# 控制器重定向到外部 url

    我使用 C 控制器作为网络服务 在其中我想将用户重定向到外部网址 我该怎么做 Tried System Web HttpContext Current Response Redirect 但没有成功 使用控制器的重定向 http msdn
  • 如何从网站下载 .EXE 文件?

    我正在编写一个应用程序 需要从网站下载 exe 文件 我正在使用 Visual Studio Express 2008 我正在使用以下代码 private void button1 Click object sender EventArgs
  • Qt 创建布局并动态添加小部件到布局

    我正在尝试在 MainWindow 类中动态创建布局 我有四个框架 它们是用网格布局对象放置的 每个框架都包含一个自定义的 ClockWidget 我希望 ClockWidget 对象在调整主窗口大小时相应地调整大小 因此我需要将它们添加到
  • 无法将类型“System.IO.Stream”隐式转换为“Java.IO.InputStream”

    我提到了一些类似的问题 但没有一个涉及IO 当我使用时 我在java中使用了相同的代码Eclipse 那次就成功了 但现在我尝试在中使用这段代码Mono for Android C 它不起作用 我正在尝试运行此代码来创建一个InputStr
  • 如何重置捕获像素的值

    我正在尝试创建一个 C 函数 该函数返回屏幕截图位图中每四个像素的 R G 和 B 值 这是我的代码的一部分 for int ix 4 ix lt 1366 ix ix 4 x x 4 for int iy 3 iy lt 768 iy i
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选
  • 如何在c#中的内部类中访问外部类的变量[重复]

    这个问题在这里已经有答案了 我有两个类 我需要声明两个类共有的变量 如果是嵌套类 我需要访问内部类中的外部类变量 请给我一个更好的方法来在 C 中做到这一点 示例代码 Class A int a Class B Need to access
  • 有没有一种简单的方法可以让 Visual Studio 2015 使用特定的 ToolsVersion?

    使用特定版本构建项目或解决方案时msbuild我可以使用以下命令选择早期的 net 工具链 toolsversion or tv switch C Program Files x86 MSBuild 14 0 bin msbuild tv
  • 我在在线程序挑战编译器中遇到演示错误

    include
  • 双精度类型二维多维数组的 pinvoke 编组作为 c# 和 c++ 之间的输入和输出

    我有以下我正在尝试解决的双物质类型的 2d 多维数组的 c 和 c pinvoke 编组 我已经查看了以下热门内容以获得我目前拥有的内容使用双精度数组进行 P Invoke 在 C 和 C 之间编组数据 https stackoverflo
  • 带重定向标准流的 C# + telnet 进程立即退出

    我正在尝试用 C 做一个 脚本化 telnet 项目 有点类似于Tcl期望 http expect nist gov 我需要为其启动 telnet 进程并重定向 和处理 其 stdin stdout 流 问题是 生成的 telnet 进程在
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐

  • CMake RelWithDebInfo 链接到调试库

    我有一个项目链接到六个库 其中包括 OpenCV 由于发布变体崩溃了 而调试工作正常 只是慢了很多 我想在中编译我的项目RelWithDebInfo配置 然而 DebugOpenCV 库的版本被包含在内 而不是Release OpenCV
  • 改变向量的元素

    假设我有一个包含数千个元素的向量 如果我想让索引在100 200之间的元素变成0 需要什么R代码 另外 我如何计算两个不同值之间的长度 例如 如果我想知道 股价 在 30 40 之间的时间长度 请阅读安装时附带的 R 简介 手册 你的问题之
  • Excel 隐藏/显示功能区上除自定义选项卡之外的所有选项卡

    如何使用 VBA 而不是 XML 隐藏和显示所有标准 Excel 功能区选项卡 我不想隐藏整个功能区 正如这里所要求的 VBA 最小化 Excel 中的功能区 https stackoverflow com questions 190195
  • 添加自定义刻度和标签

    我想在 matplotlib 中添加自定义主要刻度和标签 典型用途是在该位置添加标签math pi与标签 pi 我的目标是让其他刻度保持原样 我想保留原始的主要和次要刻度以及之前选择的格式 但带有这个额外的刻度和标签 我已经找到了一种方法
  • 使用 1:n 中的唯一值创建 n × n 矩阵

    我想在 R 中生成一个随机的 n n 矩阵 离散值范围从 1 到 n 棘手的部分是我希望每个值在行和列中都是唯一的 例如 如果n 3矩阵可能如下所示 1 2 3 2 3 1 3 1 2 或者它可能看起来像这样 2 3 1 1 2 3 3 1
  • 我的 git 存储库中的所有这些隐藏('._' 前缀)文件是什么?

    当我在目录上执行 git status 时 它会显示一堆未跟踪的文件 这些文件似乎是重复的 唯一的区别是它们都有一个前缀 例如 我需要添加的未跟踪文件之一是 app assets stylesheets categories css另一个文
  • 如何在 angular2 中显示/隐藏 div 的动态 id

    这里执行了 kpiName 的循环 并且也执行了 subRegion 的内部循环 结果 4 divclass col xs 2 创建并在其中创建两个 div 过滤器类内的可点击 div 其动态 ID 为id filteredTabSubRe
  • 如何从 Pyspark 中的日期列中减去天数列?

    给定以下 PySpark DataFrame df sqlContext createDataFrame 2015 01 15 10 2015 02 15 5 date col days col 如何从日期列中减去天数列 在此示例中 结果列
  • Java 中的 Ruby 解析器

    我正在做的项目是用 Java 和解析器源代码文件编写的 到目前为止的 Java src 现在我也想启用解析 Ruby 代码 因此 我正在寻找一个可以解析 Ruby 源代码的 Java 解析器 到目前为止我唯一能找到的是 Ruby 中的 Ru
  • 从批处理文件运行 python 脚本时出现 ModuleNotFoundError

    我有一个简单的 python 脚本 名为sc py翻译一个词 这是我的代码 python3 from googletrans import Translator import sys translator Translator dest h
  • Excel VBA 创建文件夹、子文件夹和更多子文件夹

    我有一个问题与我在这里看到的其他一些问题非常相似 但它们并没有完全回答我需要的问题 或者当我尝试它们时 它导致了一个我不知道如何解决的错误 只有5级我无法发表评论来提问 在 Excel 中 我有一个用于引用文件夹的命名配置文件的文件 我尝试
  • kerascompute_output_shape不适用于自定义层

    我自定义了一个层 将batch size和第一个维度合并 其他维度不变 但是compute output shape好像没有效果 导致后面的层无法得到准确的形状信息 从而产生错误 如何使compute output shape工作 impo
  • C++ 函数返回字符串数组

    我是 C 新手 对于一个学校项目 我需要创建一个能够返回字符串数组的函数 目前我的标题中有这个 Config h string getVehicles void 配置文件 string Config getVehicles string t
  • docker-compose:删除容器名称的默认后缀?

    my yml version 3 services myservice image myimage 当我跑步时docker compose p myprefix f my yml up 它创建名为myprefix myservice 1 是
  • 如何在没有数据库锁的情况下并行执行线程并在sqlite数据库中插入相应的数据?

    我需要调用多个 api 每个 api 在单独的线程中执行 并将响应中的相应数据插入到 sqlite 数据库中 而不会导致锁定 任何人都可以在这方面帮助我提供一个我可以参考的工作示例 我需要调用多个 api 每个 api 在单独的线程中执行
  • 我应该在哪里存储外键?

    如果我在两个表之间存在关系 两个表都有自己的主键 那么什么应该指导我决定哪个表应该存储外键 我知道关系的性质可能很重要 一对一 一对多 多对多 单向 双向 并且访问模式可能也很重要 那么做出这个决定的系统方法是什么 关系中的子表是哪个表 回
  • 微服务架构松散耦合的复杂性

    我对整个微服务潮流相当陌生 我一直在研究良好的微服务环境背后的架构和原理 定义微服务的主要内容之一应该是每个服务的松散耦合性质 微服务A永远不应该打电话微服务B直接 或者您正在有效地创建一个整体系统 该系统失去了架构模式提供的可扩展性 问题
  • 如何获取由 vector::reserve() 分配的缓冲区的地址?

    我有一个 std vector 值 我知道其最大大小 但实际大小在使用过程中会有所不同 void setupBuffer const size t maxSize myVector reserve maxSize void addToBuf
  • 通过 hibernate 或连接池保证请求

    使用连接池的休眠是否需要重试来处理间歇性故障 例如网络问题 我的同事认为这不是使用连接池的必然原因 如果连接出现任何问题 那么连接池管理器会处理它 我不相信 因为连接可能是开放且有效的 但是当发出请求时 它可能会屈服于网络问题 由于正在做的
  • 异步和等待 - 处理对同一方法的多次调用 - 相互锁定/等待?

    我有一个复杂的基于任务 锁的混乱来执行 长 数据操作 并且我正在尝试用异步 等待替换它 我是异步等待的新手 所以我担心我犯了一些大错误 为了简化事情 我的 UI 有几个页面依赖于相同的数据 现在 我只需要获取这些数据一次 所以我缓存它 进一