【问题标题】:Sequentially call asynchronous methods in a loop在循环中顺序调用异步方法
【发布时间】:2023-03-11 16:50:02
【问题描述】:

我正在处理一些代码,它具有我以前从未处理过的方法,并希望有人能够提供知识的火花:

实际上这个类是这样设置的:

void Loop()
{
    for (int i = 0; i < 100; i++)
    {
        //need to block calls to this until UpdateComplete is hit
        Update(i);
    }
}

void Update(int i)
{
    //asynchronous - returns immediately
}

void UpdateComplete()//called from another thread
{
    //unblock further calls to Update();
}

需要注意的是,在 UpdateComplete() '返回'或被回调之前,不能调用 Update()。

忽略任何 UI 副作用,是否有一个巧妙的解决方案来解决这个问题?

我目前有两种策略 - 一种很老套,一种我觉得过于复杂:

1 - Hacky:设置一个全局类布尔值IsBlocked,Update() 设置为true,UpdateComplete() 设置为 false,在我的 for 循环中(在 Loop() 中),只需放入一个 @ 987654329@.

2 - 过于复杂:完全摆脱循环。而是从Loop() 内部调用Update(0);,并让UpdateComplete() 调用Update(1);、Update(2); 等等。

我想我希望像Thread.Pause 这样的东西可以被另一个线程远程“恢复”(调用UpdateComplete() 的单独线程) 任何想法表示赞赏!

【问题讨论】:

  • 我会使用async/await
  • 把代码放在它所属的地方。向 Update() 添加另一个参数,一个名为“executeAsychronously”的布尔值。
  • 您描述的两种方式都没有提供线程的任何优势。它们始终有效地在单个线程上运行,它们只是从一个线程跳到另一个线程。所以它只会使事情复杂化。

标签: c# multithreading events


【解决方案1】:

这里也可以使用异步/等待

TaskCompletionSource<object> tcs = null;

async void Loop()
{
    for (int i = 0; i < 100; i++)
    {
        tcs = new TaskCompletionSource<object>();
        Update(i);
        await tcs.Task;
    }
}

void Update(int i)
{
    //asynchronous - returns immediately
}

void UpdateComplete()//called from another thread
{
    tcs.TrySetResult(null);
    //unblock further calls to Update();
}

【讨论】:

  • 这很酷 - 我认为tcs.TrySetResult(null); 从不同的线程调用时会起作用吗?
  • @maxp 是的,顺便说一句:如果您在UpdateComplete 中有一些数据要返回到Loop 方法,您可以通过TrySetResult 传递它。那么你的等待代码将是var some data = await tcs.Task
【解决方案2】:

使用 QueueUserWorkItem 将更新发布到线程池

有一个发布项目数量的计数器。

让主线程等待 AutoResetEvent

当每次更新完成时减少锁定计数。

当计数达到 0 时设置 AutoResetEvent 唤醒主线程

我没有发布任何代码,因为我假设你可以谷歌如何做每一位,如果没有评论,我可以添加代码

【讨论】:

  • 有趣,我会研究一下(顺便说一句,这不是我的反对意见)
  • @maxp 如果这种方法对您来说听起来合理,您应该更新您的问题 - 目前听起来所有项目必须按顺序处理(而这篇文章建议并行执行)。 - 这种不匹配可能是(不是我的)投反对票的原因,并且也阻止了对这篇文章的投赞成票。
  • @AlexeiLevenkov 是的,你是对的,它们必须是连续的。
  • @maxp - 我已根据此评论更新了帖子的标题 - 请检查并在必要时回滚/更新。
猜你喜欢
  • 2012-03-15
  • 2011-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多