-1

i have button1_click method like this

 private async void button1_Click(object sender, EventArgs e)
    {


        Task<string> st1 = Task.Run(() => ReadFromFile());
        textBox1.AppendText("sdsadsa");
        textBox1.Text = st1.Result;



    }

i want to read from text file with ReadFromFile()

Note : ReadFromFile is marked with async because i want to use async and await in this method

to planning some Task methods

but my Ui is freezing after append text method calling in line 2 in my button1_click method

and wait the result and show it in text box.

i want to throw the ReadFromFile method in task and await it without ui freezing

i tried many things like replacing line 1 with this

Task<string> st1 = await Task.Factory.StartNew(() => ReadFromFile());

with this, ui dont freeze but it skips line 2 the append method , i dont know why this skiping?

  • 3
    If you are working with `async..await` you should not use `.Result;` (i.e. `st1.Result`); `textBox1.Text = await st1;` – Dmitry Bychenko Oct 08 '19 at 10:21
  • 1
    _"...ReadFromFile is marked with async because i want to use async and await in this method..."_ - If you have code in `ReadFromFile` that is already using `async` I/O methods then you should not be wrapping the call in a `Task.Run`. The latter is for CPU-bound operations not I/O. You are wasting a thread –  Oct 08 '19 at 10:29
  • ohh thanks Dmitry Bychenko it is working but i have a question , When should i use Result method ??? – Mohamed Saleh Oct 08 '19 at 11:28
  • ohh MickyD I understand u , but when i use method caller or for loop in ReadFromFile method without Task.run , ui will freeze – Mohamed Saleh Oct 08 '19 at 11:30
  • @MickyD calling `Task.Run` with an async delegate as argument is not wasting a thread. `Task.Run(async () =>...` is certainly not intended for CPU bound operations. In OP's case a thread will be wasted (blocked) only if the `ReadFromFile` is not a `Task`-returning method. – Theodor Zoulias Oct 08 '19 at 12:50
  • @TheodorZoulias true, but I don’t believe either scenario applies to OP’s case. In order to use async delegate ReadFromFile would **ideally** have to be async anyway and if so, again why bother with Task.Run to run code that is already async-aware? Particularly for I/O? It is a bad pattern. –  Oct 08 '19 at 19:58
  • @MickyD he is calling it inside an UI event handler. Ensuring that the async method will run in a thread-pool thread is the correct thing to do. Otherwise he risks blocking the UI, in case the `ReadFromFile` method contains hybrid code (synchronous and asynchronous). – Theodor Zoulias Oct 08 '19 at 20:41
  • @TheodorZoulias incorrect. He merely needs to use `async` all the way and call `await` and not `.Result`. No need for `Task.Run` or the dangerous `Task.Factory.StartNew`. https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html –  Oct 08 '19 at 20:44
  • @MickyD please look at [an example](https://stackoverflow.com/a/58279477/11178549) I posted in another question today, that shows an async hybrid that will get you into trouble if you `await` it directly (without `Task.Run`). It is the method `ExternalMethodAsync`. – Theodor Zoulias Oct 08 '19 at 20:47

1 Answers1

2

Just await ReadFromFile:

private async void button1_Click(object sender, EventArgs e)
{
    string st1 = await ReadFromFile();
    textBox1.AppendText("sdsadsa");
    textBox1.AppendText(st1);
}
Alberto
  • 15,626
  • 9
  • 43
  • 56
  • yeah i know this but if i add any method caller in ReadFromFile or use for or while loop , ui will freeze . – Mohamed Saleh Oct 08 '19 at 11:21
  • @MohamedSaleh it won't freeze if you [avoid blocking asynchronous code](https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html) by using `Result`. You'd better forget about this property, especially now that are still not very experienced with asynchronous programming. Will cause you problems and more problems. Just use `await` everywhere. – Theodor Zoulias Oct 08 '19 at 12:56