-2

Here's the code that I have now:

int rpt = Settings.rpt;
while (rpt > -1)
{
   await ShowPhraseHeading();
   await ShowPhraseDetail();
   await ShowSleep();
   rpt--;
}

I am wondering if there is another way that I can do this that would be a bit cleaner such as with a foreach or maybe even LINQ.

JBoothUA
  • 3,040
  • 3
  • 17
  • 46
Alan2
  • 23,493
  • 79
  • 256
  • 450

4 Answers4

2

More concise? I'd say you're near the limit already; the only line I could realistically eliminate is rpt--; (by hoisting it up: while (rpt-- > -1) { ... }). All other ways I can imagine of implementing the same logic lead to less terse code.

This should run your group of asynchronous methods in parallel using LINQ to generate a list of tasks:

var tasks = Enumerable
    .Range(0, Settings.rpt)
    .Select(async _ => {
        await ShowPhraseHeading();
        await ShowPhraseDetail();
        await ShowSleep();
    });

await Task.WhenAll(tasks);

To be clear, ShowPhraseHeading(), ShowPhraseDetail(), and ShowSleep() should happen sequentially within each block while the blocks themselves will run in parallel. If you want/need everything to run sequentially then maybe go with this? (I personally like your existing code style better):

Enumerable
    .Range(0, Settings.rpt)
    .Select(async _ => {
        await ShowPhraseHeading();
        await ShowPhraseDetail();
        await ShowSleep();
    })
    .Select(task => task.GetAwaiter().GetResult()) // wait for each block to complete
    .ToList(); // a dumb way to force enumeration

Note: I chose not to iterate backwards because it didn't seem to matter in your particular case; .Reverse() might be appropriate if you need to change direction at any point.

Assuming that one chooses to run things in parallel then it might be a good idea to check out the posts here in order to put a limit on the maximum degree of parallelism.

Kittoes0124
  • 4,930
  • 3
  • 26
  • 47
1

you could use a for loop

for (int rpt = Settings.rpt; rpt > -1; rpt--)
{
    await ShowPhraseHeading();
    await ShowPhraseDetail();
    await ShowSleep();
}

if you had a list of Settings or any enumerable you could use a foreach loop.

var settings = new List<Settings>();
...
foreach (var setting in settings)
{
    await ShowPhraseHeading();
    await ShowPhraseDetail();
    await ShowSleep();
}
JBoothUA
  • 3,040
  • 3
  • 17
  • 46
  • Thanks, but in your example it counts up and my code counts down – Alan2 Oct 06 '18 at 03:18
  • 2
    i dont think it matters, if you do not use the variable "rpt", but I will update the code – JBoothUA Oct 06 '18 at 03:20
  • You can count up or down in a `for`. There are three parts to a `for`, an initializing part, a decision part (which continues the loop if a bool is `true`, and a part that runs at the end of every pass through the loop's block. You can make a loop count up (as normal), count down, or do almost anything else. – Flydog57 Oct 06 '18 at 04:06
1

You could write it this way:

for ( int rpt = Settings.rpt; rpt>-1; rpt-- )
{
    await ShowPhraseHeading();
    await ShowPhraseDetail();
    await ShowSleep();
}

Also, unless you want the different "Show" steps to happen in sequence, it'd be slightly more efficient to let them run in parallel like this:

for ( int rpt = Settings.rpt; rpt>-1; rpt-- )
{
    await Task.WhenAll
    (
        ShowPhraseHeading(),
        ShowPhraseDetail(),
        ShowSleep()
    );
}
John Wu
  • 50,556
  • 8
  • 44
  • 80
0

I don't know about more concise, but when your loop variable must be initialized and/or incremented/decremented, I really think it makes better sense to use a for loop so that all that logic is grouped together in one construct.

int rpt;

for (rpt = Settings.rpt; rpt >= 0; i--)
{
   await ShowPhraseHeading();
   await ShowPhraseDetail();
   await ShowSleep();
}
Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466