11

I have want to run a function asynchronously to prevent UI freezing. Here the the button click event.

private void btnEncrypt_Click(object sender, EventArgs e)
{
    // Create new Vigenere object instant
    cryptor = new Vigenere(txtPassword.Text, txtBox.Text);

    // Run encryption async
    Task<string> T = new Task<string>(cryptor.Encrypt);
    T.Start();
}

Now I want the following function to be called when the Task T finishes with it's return value as a parameter like this:

private void Callback(string return_value)
{
    txtBox.Text = return_value

    // Some other stuff here
}

How to achieve this?

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Xbyte Finance
  • 173
  • 1
  • 1
  • 9

3 Answers3

16

What you could do is use the ContinueWith(Action<Task>) method.

So you would have something like

Task<string> t = new Task<string>(cryptor.Encrypt);
T.Start();

Task continuationTask = t.ContinueWith((encryptTask) => {
    txtBox.Text = encryptTask.Result;
    ...
})

Effectively this just says do the action after the current task completes, completion could be successful running, faulting or exiting early due to cancellation. You would likely want to do some error handling to make sure you didn't try to use the result of a cancelled or faulted task.

Stephen Ross
  • 882
  • 6
  • 21
  • 2
    But the problem is ContinueWith action doesn't execute on the main thread, it executes in the worker thread in my case! – Mohit Atray May 17 '20 at 12:48
4

First, add async to your button click event. Try:

private async void btnEncrypt_Click(object sender, EventArgs e)
{
     cryptor = new Vigenere(txtPassword.Text, txtBox.Text);
     await Task.Run(() => cryptor.Encrypt()).ContinueWith(result => { Callback(result.Result); });
}
Borophyll
  • 1,099
  • 2
  • 15
  • 24
1

You want to use Task.Run and await on it. This will make the method execute on a thread-pool thread, and assign the returned string to the TextBox once it completes:

private async void btnEncrypt_Click(object sender, EventArgs e)
{
     cryptor = new Vigenere(txtPassword.Text, txtBox.Text);
     textBox.Text = await Task.Run(() => cryptor.Encrypt());
}
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321