Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# async await a button click [duplicate]

I'm new to c# async await mechanism. I have checked all the previous examples of async, await but none of them is exactly like mine. what I would like to do? I have a foreach loop and I would like to stop it on a certain rule, do some stuff and continue running by clicking on a button. Here is simple code example:

private void RunConvert()  // START 
{
    foreach (PartSettings File in PartsFromXLS)  // RUNING THE FOREACH LOOP ON A LIST
    {
        ProcessSinglePart(PathStep, PathMCX);
    }
}

public static async void ProcessSinglePart(string PartPathToRead, string PartPathToSave)
{
    // DO SOME STUFF BEFORE THE CHECK

    if (PartLength < PartWidth) // SOME CHECK VALUES
    {
         await WhenClicked();  //HERE I WOULD LIKE TO WAIT FOR BUTTON CLICK
    }

    //DO SOME STUFF AFTER THE CHECK
}

private void GeometryOK_Click(object sender, EventArgs e) 
{
    //  I WOULD LIKE TO WAIT FOR THIS CLICK
}
like image 476
Primoz Krzic Avatar asked Nov 04 '25 17:11

Primoz Krzic


1 Answers

await suspends execution of a method until the argument (which must be a Tasklike, in practice, its just a Task or Task<T>) completes. Your issue is actually one that I've run into a number of times:

How to asynchronously wait for some event to be fired

In your case "some event" is a button click. Luckily, TaskCompletionSource<T> (hereafter, TCS) is pretty much ideal for solving this. First declare a TCS at the class level:

private TaskCompletionSource<bool> clickWaitTask;

There's no non-generic version of a TCS so I usually just use bool. We don't actually care about the data in this case. Then your method looks like this (explanation to follow):

public static async void ProcessSinglePart(string PartPathToRead, string PartPathToSave)
{
    // DO SOME STUFF BEFORE THE CHECK
    clickWaitTask = new TaskCompletionSource<bool>();

    if (PartLength < PartWidth) // SOME CHECK VALUES
    {
         await clickWaitTask.Task;
    }

    //DO SOME STUFF AFTER THE CHECK
}

You create a new TCS so that each time this logic is run, it will wait for the click to occur. Then you await the Task property (which is, in fact, a Task<T>). That task will only complete when TrySetResult is called on the TCS object. Do that in your button click handler (or command handler for WPF):

 clickWaitTask.TrySetResult(true); //Value does not matter

As a commenter noted, you shouldn't use async void unless you are in a event handler, and should have try/catch around the method in that case to avoid some nastiness with unhandled exceptions. I'm also extremely wary of your public static but that's a separate problem.

like image 125
BradleyDotNET Avatar answered Nov 07 '25 11:11

BradleyDotNET



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!