我是否需要调用以从异步方法访问 DataGridView.SelectedRows?
Do I need invoke to access DataGridView.SelectedRows from a async method?
我有这样的方法:
async Task foo() {
foreach (DataGridViewRow row in dataGridView1.SelectedRows) {
// ...
}
}
这样调用:
await Task.Run(() =>
{
foo();
});
我刚刚注意到代码正在直接访问 dataGridView1.SelectedRows
,无需调用,并且运行良好。我执行的操作无效吗?这应该有效还是我必须在这里使用 invoke?
这是因为你使用了async
和await
,而不是创建一个新的Thread/BackgroundWorker。
在我看来,与 Controls
.
交互时使用 Invoke 从来都不错
官方的回答是取决于谁调用了你的foo函数。它是主线程,还是其他线程?
如果它是主线程(更好:创建控件的线程),则不需要调用。异步不影响这个
以下由 UI 线程完成,并且可以正常工作。
public async void Button1_Clicked(object sender, ...)
{
await Foo();
}
很多时候人们认为async-await 是由多个线程完成的。但事实上并非如此。异步函数中的线程执行所有语句,直到遇到等待。它并没有真正等到等待的函数完成,而是在其调用堆栈中上升以查看它是否可以做其他事情。
这在 Eric Lippert's restaurant metaphor 中得到了完美的解释(在页面上搜索异步)。厨师没有等到面包烤好,而是开始煮鸡蛋。但还是那个厨师
当您看到在没有等待的情况下调用异步函数的代码时,线程将执行调用直到遇到等待,并且将在未等待的调用之后执行语句,而不是什么都不做。
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();
}
这个 taskFoo 的 await 有效果控制被交还给我的调用者(仍然是同一个线程),直到我的调用者等待。在那种情况下,控制权交给他的呼叫者,直到 await 等
唯一一次涉及不同的线程是在您主动启动它时,通常使用:
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。
关于异步等待的另一个有用的故事:Stephen Cleary about async-await
我有这样的方法:
async Task foo() {
foreach (DataGridViewRow row in dataGridView1.SelectedRows) {
// ...
}
}
这样调用:
await Task.Run(() =>
{
foo();
});
我刚刚注意到代码正在直接访问 dataGridView1.SelectedRows
,无需调用,并且运行良好。我执行的操作无效吗?这应该有效还是我必须在这里使用 invoke?
这是因为你使用了async
和await
,而不是创建一个新的Thread/BackgroundWorker。
在我看来,与 Controls
.
官方的回答是取决于谁调用了你的foo函数。它是主线程,还是其他线程?
如果它是主线程(更好:创建控件的线程),则不需要调用。异步不影响这个
以下由 UI 线程完成,并且可以正常工作。
public async void Button1_Clicked(object sender, ...)
{
await Foo();
}
很多时候人们认为async-await 是由多个线程完成的。但事实上并非如此。异步函数中的线程执行所有语句,直到遇到等待。它并没有真正等到等待的函数完成,而是在其调用堆栈中上升以查看它是否可以做其他事情。
这在 Eric Lippert's restaurant metaphor 中得到了完美的解释(在页面上搜索异步)。厨师没有等到面包烤好,而是开始煮鸡蛋。但还是那个厨师
当您看到在没有等待的情况下调用异步函数的代码时,线程将执行调用直到遇到等待,并且将在未等待的调用之后执行语句,而不是什么都不做。
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();
}
这个 taskFoo 的 await 有效果控制被交还给我的调用者(仍然是同一个线程),直到我的调用者等待。在那种情况下,控制权交给他的呼叫者,直到 await 等
唯一一次涉及不同的线程是在您主动启动它时,通常使用:
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。
关于异步等待的另一个有用的故事:Stephen Cleary about async-await