我是否需要从异步方法调用以访问DataGridView.SelectedRows?

时间:2016-05-19 02:32:55

标签: c# winforms datagridview async-await invoke

我有这样的方法:

 async Task foo() {
         foreach (DataGridViewRow row in dataGridView1.SelectedRows) {
         // ...
        }
}

这样叫:

await Task.Run(() =>
                    {
                        foo();
                    });

我只是注意到代码是直接访问dataGridView1.SelectedRows,没有调用,而且工作正常。我执行的操作无效吗?这应该是可行的还是我必须在这里使用调用?

2 个答案:

答案 0 :(得分:1)

官方的答案是,取决于谁调用你的foo功能。它是主线程,还是可能是不同的线程?

如果它是主线程(更好:创建控件的线程),则不需要调用。异步不影响这个

以下内容由UI线程完成,并且可以正常工作。

public async void Button1_Clicked(object sender, ...)
{
     await Foo();
}

人们常常认为async-await是由几个线程完成的。但事实上并非如此。异步函数中的线程执行所有语句,直到满足等待。它没有真正等到等待的函数完成,而是在其调用堆栈中上升,以查看它是否可以执行其他操作。

Eric Lippert's restaurant metaphor(在异步页面上搜索)完美解释了这一点。厨师开始煮鸡蛋,而不是等到面包烤了。但它仍然是同一个厨师。

当你看到没有await的情况下调用异步函数的代码时,线程会在遇到await之前执行调用,并在未等待的调用之后执行语句而不是什么都不做。

private async void Button1_clicked(object sender, ...)
{
    var taskFoo = this.Foo()
    // because not await: the thread will do the things in Foo until it meets
    // an await. Then it returns back to do the next statements:

    DoSomething();

    // if this function has nothing more to do, or if it needs the result
    // of Foo, await Foo:
    await taskFoo;

    ProcessFooResult();
}

这等待for taskFoo将效果控制权交还给我的调用者(仍然是同一个线程),直到我的调用者等待。在那种情况下,控制权将给予他的来电者,直到等待等等。

唯一涉及不同线程的时间是您主动启动它时,通常使用:

var myTask = Task.Run( () => DoSomething() );
// Because there is no await, your thread will do immediately the next
// statements until an await:

DoOtherThings();
await myTask();

现在DoSomething由另一个线程执行。如果您需要访问UI控件,则需要InvokeRequired和Invoke。

关于async-await的另一个有用的故事:Stephen Cleary about async-await

答案 1 :(得分:0)

这是因为您使用asyncawait而不是创建新的线程/ BackgroundWorker。 在我看来,在与Controls进行交互时使用Invoke绝对不错。