12

I have an I/O bound method that I want to run asynchronously.

In the help docs it mentions that I should use async and await without Task.Run

to quote

For I/O-bound code, you await an operation which returns a Task or Task inside of an async method.

How do I do this from a winforms button click event?

I have tried

private void button_Click(object sender, EventArgs e)
{ 
      await doLoadJob();
}

private async Task<int> doLoadJob()
{
    await loadJob();   
    return 0;
}
Kirsten
  • 15,730
  • 41
  • 179
  • 318
  • 5
    `private async void button_Click(object sender, EventArgs e)` – JohanP Aug 03 '18 at 01:55
  • In order to truly benefit from asynchronicity, you need it all the way down. If `loadJob` is yours, make it `async` too. If it's library code, is there a `loadJobAsyc` (or `loadJobTaskAsync`) available? – Damien_The_Unbeliever Aug 03 '18 at 06:19
  • It seems clear that `loadJob()` is a sync method, not an async one, so the warning you receive already has the answer: "or 'await Task.Run(...)' to do CPU-bound work on a background thread". So use `await Task.Run(() => loadJob())` in your handler (as well as make the handler async, as others have said). It would be better to make `loadJob()` async, if you can, but as long as it remains sync, you need to do this. – sellotape Aug 03 '18 at 06:28
  • @sellotape - the OP describes their task as I/O bound, not CPU-bound, so using `Task.Run()` is usually the wrong choice. – Damien_The_Unbeliever Aug 03 '18 at 06:36
  • @damien_the_unbeliever - I agree it's probably mostly I/O bound (as a database call), but if it's sync I/O it will still need `Task.Run()`, until/unless it is also made async. – sellotape Aug 03 '18 at 06:54
  • @KirstenGreed - you've changed the question so much now that a coherent answer is unlikely. Re your latest edit, I/O bound code is not magically async; it's instead usually _very well suited to being made async_. `loadJob()` appears to be sync, regardless of the nature of its activity. As long as it's sync, you have to use `Task.Run()` to achieve what you want. The quote you just added says "For I/O-bound code, you await **an operation which returns a Task** or Task inside of an async method" - does `loadJob()` return a `Task`? – sellotape Aug 03 '18 at 07:12
  • @sellotape sorry about the edits they are all to try and articulate my problem which has not changed. LoadJob returns void – Kirsten Aug 03 '18 at 07:15
  • @KirstenGreed - then, assuming it can't be made async ("source code not available"), you need `Task.Run()` or the handler will block. – sellotape Aug 03 '18 at 07:21
  • Possible duplicate of [Do you have to put Task.Run in a method to make it async?](https://stackoverflow.com/questions/17119075/do-you-have-to-put-task-run-in-a-method-to-make-it-async) – Kirsten Aug 03 '18 at 07:26
  • https://stackoverflow.com/questions/17119075/do-you-have-to-put-task-run-in-a-method-to-make-it-async?rq=1 helped me a lot. I reverted the question to be like the original so that the answer makes sense. – Kirsten Aug 03 '18 at 07:31

1 Answers1

18

Your button_Click method needs to be async. Place a async between private and void.

private async void button_Click(object sender, EventArgs e)
{ 
     await LongOperation();
}
João Fernandes
  • 491
  • 7
  • 17
  • You can't move the form around because System.Threading.Thread.Sleep is affecting your main (app) thread. – RamblinRose Aug 03 '18 at 02:15
  • any suggestions how to simulate the io bound event? – Kirsten Aug 03 '18 at 02:16
  • 3
    @KirstenGreed post that into a **new question**. Stop changing the scope of your original question. Your original post shows no such code –  Aug 03 '18 at 02:28
  • Because you misrepresented the problem. It solveed the problem you presented. Accept that and make a new question and maybe spend al ittle more time providing RELEVANT examples. See, there is no sleep in your code sample, ergo it can not cause a problem. The question you DID ask got answered. – TomTom Aug 03 '18 at 06:40