【问题标题】:Pause Foreach Loop until the first Iteration is completed暂停 Foreach 循环,直到第一次迭代完成
【发布时间】:2013-07-09 21:04:51
【问题描述】:

这是我的场景:

ClassA
{
  Timer tmr = new Timer(1000);
  void Start()
     {
       tmr.start();
     }

  void tmr_Elapsed(object sender, ElapsedEventArgs e)
        {

            //Do Something
            if (myCondition==true)
            {
                //Do Something

                tmr.Stop(); // Or Change Value of a Property! anything that shows it
                            //meets the condition.
            }
        }
}


Class WorkflowController
{
   list<ClassA> allA=new list<ClassA>(){new A1,new A2, new A3}
   void Start()
   {
     foreach(item in allA)
     {
        item.start()
     } 
   }
}

问题:

现在我希望 foreach loop 执行 A1.Start() 并等到计时器满足条件(此处为 x&gt;50 并在 50 秒后)并停止。然后执行A2.Start() 并等待计时器满足条件并再次停止。然后执行A3.Start() 等等。 WorkFlowController 控制我的应用程序的工作流程。我不知道做这件事的简单方法是什么。我应该使用INotifyPropertyChanged 吗?我应该使用Eventhandler 吗?还是有更好的方法?

【问题讨论】:

  • 我希望这只是示例代码。对于计时(等待 X 秒),不要使用计时器,而是使用 StopWatch 类。要在执行任何异步操作时暂停代码执行,请使用 WaitHandle
  • 考虑使用手动重置事件
  • 呃,你是在用异步代码做同步的吗?
  • 您似乎正在尝试重新实现Task。这一切都已经为你完成了。 msdn.microsoft.com/en-us/library/dd537609.aspx

标签: c# .net multithreading async-await


【解决方案1】:

您可以使用事件处理程序来同步它

ClassA
{
  ManualResetEvent mre = new ManualResetEvent(false);
  Timer tmr = new Timer(1000);
  void Start()
     {
       tmr.start();
     }

  void tmr_Elapsed(object sender, ElapsedEventArgs e)
        {

            x++;
            if (x > 50)
            {
                //Do Something

                tmr.Stop(); // Or Change Value of a Property! anything that shows it
                            //meets the condition.
                mre.Set();
            }
        }

  public void Wait()
  { 
     mre.WaitOne();
  }
}


Class WorkflowController
{
   list<ClassA> allA=new list<ClassA>(){new A1,new A2, new A3}
   void Start()
   {
     foreach(item in allA)
     {
        item.start();
        item.Wait();
     } 
   }
}

【讨论】:

  • mre.wait() 你的意思是 mre.WaitOne()?因为它没有这个方法。
【解决方案2】:

您可以在以下实现中使用任务:

List<ClassA> all = new List<ClassA> { ... };
private async void Start()
{
    foreach (var item in all)
    {
         await item.DoWork();
    }
}

public class ClassA
{
    public async Task DoWork()
    {
        Thread.Sleep(50000); // wait 50sec
        // Do work            
    }
}

你有一个"How to: Wait on One or More Tasks to Complete" here

希望对你有帮助!

【讨论】:

  • 启动方法是异步的,也应该同步。
  • DoWork 完成后 foreach 循环如何理解继续?我正在使用计时器!
  • 我的代码是一个在异步方法上循环的例子,等待它完成后再循环。您可以根据自己的情况进行调整。
  • @JoffreyKern 真的很抱歉,但你能帮我用你的方式实现我的代码吗?我真的很感激
  • @JoffreyKern 哦不!我认为你不理解这个问题(或者我解释得不好)(x>50)只是一个示例代码。实际上,它是我的应用程序中更大工作流程的一部分。为了简单起见,我只是写了 (x>50) 。每次滴答我都会计算一些东西,直到我到达需要的点,然后我停止计时器。我不想只等 50 秒。
【解决方案3】:
private async void Start()
{
    foreach (var item in all)
    {
         await item.DoWorkAsync();
    }
}

public class ClassA
{
    public async Task DoWorkAsync()
    {
        bool done = false;

        while(!done)
        {
            DoStuff();
            DoMoreStuff();

            if(someCondition)
            {
                done = true;
            }
            else
            {
                await Task.Delay(1000);
            }
        }
    }
}

【讨论】:

【解决方案4】:

实际上,您的代码似乎没有什么不同。

for(var i = 0; i < 3; i++)
{
    Thread.Sleep(1000)
    Task.Wait(Task.StartNew(() =>
        {
            //Do Something
            if (myCondition==true)
            {
                // Do Something
                // Or Change Value of a Property! anything that shows it
                // meets the condition.
            }
        });
}

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多