2

I want to add a delay after every iteration in a foreach loop, so the Treat method gets called only every 2 seconds. I do not want to use Thread.Sleepbecause I want to still be able to use my program while the loop is running. I'm trying to tell the foreach loop to wait 2 seconds before doing the next iteration. Here's what I have so far:

 public async void HandlingAsync(ListViewItem woodItem) { IList<ListViewItem> woodList = new List<ListViewItem>(); woodList.Add(woodItem); foreach(ListViewItem Item in woodList) { await Task.Delay(2000); Treat(Item); } } public void Treat(ListViewItem woodItem) { woodItem.SubItems[3].Text = "dried"; woodItem.SubItems[4].Text = "Ok"; } 

This doesn't work because the await command doesn't affect the foreach loop, only the commands inside of it. I can confirm that, because the ListView changes its items all at the same time, while it should change one item and wait 2 seconds before changing the next item.

EDIT: Marc Gravell ist right. The foreach loop absolutely respects the await command. So his answer works 100%. My problem was neither in the foreach loop nor in the await command. It didn't work because my HandlingAsync Method got called multiple times. This results in calling the Treat Method almost instantly muliple times. That means, that every woodItem got changed at the same time with a delay of 2 seconds. To solve this, the HandlingAsync should only be called once. Thanks for your help.

13
  • What do you mean by the await command doesn't affect the foreach loop? It's the asynchronous version of doing a Thread.Sleep. What exact results are you getting from this that are not what you expect? Commented Aug 28, 2018 at 14:33
  • You could use Thread.Sleep(2000); Commented Aug 28, 2018 at 14:33
  • 3
    "The foreach loop doesn't get affected by await," - yes it does; it really does; if something isn't working quite right, that's fine - but: foreach absolutely respects the await here Commented Aug 28, 2018 at 14:42
  • 1
    How exactly are you determining that the delay isn't occurring? Commented Aug 28, 2018 at 14:43
  • 1
    to explain @WiktorZychla's point - it sounds like the issue here is that repaint is suspended during this loop. You can use DoEvents to force it, but ... that's pretty horrible in many ways, and any time you can avoid DoEvents, you should avoid DoEvents. Are you sure there isn't an explicit "disable paint" / "suppress changes" / etc call before your loop? Commented Aug 28, 2018 at 14:49

1 Answer 1

7

foreach respects await just fine; here's an example in a console:

static async Task Main() { string[] woodList = { "maple", "ash", "oak", "elm", "birch" }; foreach (string wood in woodList) { Treat(wood); await Task.Delay(2000); } } private static void Treat(string wood) { Console.WriteLine($"{DateTime.Now}: treating {wood}"); } 

the output for me is (with obvious pauses):

28/08/2018 15:45:10: treating maple 28/08/2018 15:45:12: treating ash 28/08/2018 15:45:14: treating oak 28/08/2018 15:45:16: treating elm 28/08/2018 15:45:18: treating birch 

So: if your code isn't behaving as expected - the problem isn't with the foreach/await. Can you perhaps show more of the surrounding context, and indicate what makes you think it isn't working?

Sign up to request clarification or add additional context in comments.

2 Comments

I updated my question and added some code. My foreach loop continues without waiting 2 seconds. I can see that, because my ListView changes all its items a the same time.
@CaramelBailey's hence my question in the comments about whether there's some code that is suppressing UI updates

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.