Denis Lolik
Denis Lolik

Reputation: 329

How to avoid WinForm freezing using Task.Wait

So I have code something like that

private void doSmth()
{
   str = makeStr();
}
private void button_Click(object sender, EventArgs e)
{
   Task task = new Task(doSmth);
   task.Start();
   task.Wait();
   textBox.Text = str;
}

It's freezing and I know why this is happening because of Wait(). I was trying to use ContinueWith() like this

task.ContinueWith((t) => {textBox.Text = str;});

But it doesn't work throwing an InvalidOperationException:

The calling thread cannot access this object because a different thread owns it

How can I fix this? Maybe I should use completely another approaches to implement what I want to. Thanks.

Upvotes: 1

Views: 3317

Answers (3)

MKH
MKH

Reputation: 367

Try do this, it works for me :

Task ts =new Task(new Action(()=>{
//your code here
}
));
ts.Start();//start task

//here we wait until task completed
while (!ts.IsComplete)//check until task is finished
{
//pervent UI freeze
Application.DoEvents();
}
//Task Completed
//Continue with ...
textBox.Text = ts.Result;

Upvotes: 0

PiranhA
PiranhA

Reputation: 164

Well first of all you have to start the task to be able to wait for it ;)
If you want to use ContinueWith() rather than async/await, you just can use the option TaskContinuationOptions.ExecuteSynchronously. This will cause the continuation operation to be executed in the calling thread.

Task task = new Task(doSmth);
task.ContinueWith(t => textBox.Text = str, TaskContinuationOptions.ExecuteSynchronously);
task.Start();
//task.Wait(); // optional if you want to wait for the result

Upvotes: 0

Dai
Dai

Reputation: 155145

You'll want this:

private String DoSomething() {

    return makeStr(); // return it, don't set it to a field.
}

private async void button_Click(...) {

    String result = await Task.Run( DoSomething );
    textBox.Text = result;
}

...which is equivalent to this:

private async void button_Click(...) {

    // Task<> is the .NET term for the computer-science concept of a "promise": https://en.wikipedia.org/wiki/Futures_and_promises
    Task<String> resultPromise = Task.Run( DoSomething ); 
    String result = await resultPromise;
    textBox.Text = result;
}

...which is (roughly) equivalent to this:

private void button_Click(...) {

    Thread thread = new Thread( () => {

        String result = DoSomething();
        this.BeginInvoke( () => {

            this.textBox.Text = result;
        } );

    } );
    thread.Start();
}

Upvotes: 7

Related Questions