0

Imagine there are two buttons that call an asynchronous function

  int packProcesses=0;  //the number of processes we are dealing with
    bool busy = false;  //are we busy?
   int v=10;
  private async void button5_Click(object sender, EventArgs e)
  {
    packProcesses++;
    busy = true;
    Trace.WriteLine("PROCESSES " + packProcesses + " busy? " + busy);
    //Do something
    var result = await DelayAndReturnAsync(v);
    //finished?
    packProcesses--;
    if (packProcesses <= 0) busy = false;
    Trace.WriteLine("Processes " + packProcesses + " busy? " + busy);
    }

    private async void button6_Click(object sender, EventArgs e)
     {
       packProcesses++;
       busy = true;
       Trace.WriteLine("PROCESSES " + packProcesses + " busy? " + busy);

        //Do something
        var result = await DelayAndReturnAsync(v);
        //finished?
        packProcesses--;
        if (packProcesses <= 0) busy = false;
        Trace.WriteLine("Processes " + packProcesses + " busy? " + busy);
        }

Where the asynchronous function is

 async Task<int>DelayAndReturnAsync(int val)
  {
   await Task.Delay(TimeSpan.FromSeconds(val)).ConfigureAwait(false);
   Trace.WriteLine("Time" + DateTime.Now);
    return val;
   }

and I want to have another button that calls both of the buttons. If I just put both click functions one after another I will have both processes started at once.

Since I want one processes to start after the other I do

 private async void button8_Click(object sender, EventArgs e)
  {
  button5_Click(sender, e);
   do
    {
     await Task.Delay(1000);
     } while (busy);
    button6_Click(sender, e);
    }

I took the idea from this answer

Is this a good idea? I don't want to clog the CPU in order to do this. Is there a better way to wait for one process to complete to start the other?

KansaiRobot
  • 7,564
  • 11
  • 71
  • 150

2 Answers2

2

You can move your logic from inside the handler to another method:

private async void button1_Click(object sender, EventArgs e)
{
    await Process1();
}

private async Task Process1()
{
    packProcesses++;
    busy = true;
    Trace.WriteLine("PROCESSES " + packProcesses + " busy? " + busy);
    //Do something
    var result = await DelayAndReturnAsync(v);
    //finished?
    packProcesses--;
    if (packProcesses <= 0) busy = false;
    Trace.WriteLine("Processes " + packProcesses + " busy? " + busy);
}

private async void button2_Click(object sender, EventArgs e)
{
    await Process2();
}

private async Task Process2()
{
    packProcesses++;
    busy = true;
    Trace.WriteLine("PROCESSES " + packProcesses + " busy? " + busy);

    //Do something
    var result = await DelayAndReturnAsync(v);
    //finished?
    packProcesses--;
    if (packProcesses <= 0) busy = false;
    Trace.WriteLine("Processes " + packProcesses + " busy? " + busy);
}

Then you can await both them:

private async void button3_Click(object sender, EventArgs e)
{
    await Process1();
    await Process2();
}
Alessandro D'Andria
  • 8,663
  • 2
  • 36
  • 32
1

if you can at all, I would try and avoid having your button6_Click and button5_Click methods returning void. if instead you have them return a Task you can await them.

private async Task button5_Click(object sender, EventArgs e) 
{ ... }

private async Task button8_Click(object sender, EventArgs e) 
{
     await button5_Click(sender, e);
     await button6_Click(sender, e);
}

edit:

private async Task HandleButton5_Click() 
{
     ...
}    

private async void button5_Click(object sender, EventArgs e) 
{  
    await HandleButton5_Click();
}

private async void button8_Click(object sender, EventArgs e) 
{
     button5_Click(sender, e);
     button6_Click(sender, e);
}
Dan Scott
  • 554
  • 3
  • 10
  • That is a very good idea! I didn't know you could change the return value of a click button function! I ll try it – KansaiRobot Jul 11 '18 at 09:25
  • If you cannot change the return type of the button click, a way to get around that may be to create another method in your source file that is an `async Task` and call that from the void button click handler and `await` it there instead – Dan Scott Jul 11 '18 at 09:27
  • I tried and it gives errors. Apparently you can not change the return value of the click buttons – KansaiRobot Jul 11 '18 at 09:29
  • yeah I got it. One question, how about in your edited code, in button8, call HandleButtonX_Click directly with await? – KansaiRobot Jul 11 '18 at 09:37
  • yeah that could work also :) but then when you click your `button5` on your form I assume it is, the button wouldn't do anything =P I assumed you were just using button8 to trigger both 5 and 6 button handlers – Dan Scott Jul 11 '18 at 09:39
  • Oh, I will leave button5 as you wrote in your answer – KansaiRobot Jul 11 '18 at 09:40