公式の答えは、あなたのfoo関数を呼び出す人に依存します。それはメインのスレッドですか、それとも別のスレッドですか?
メインスレッド(より良い:コントロールを作成したスレッド)であれば、Invokeを必要としません。非同期はこれに影響しません
以下はUIスレッドによって行われ、正常に動作します。
public async void Button1_Clicked(object sender, ...)
{
await Foo();
}
多くの場合、async-awaitは複数のスレッドによって行われると考えられます。しかし実際はそうではありません。非同期関数内のスレッドは、待機状態になるまですべてのステートメントを実行します。待機している関数が完了するまで実際に待つのではなく、呼び出しスタックに入って別のことができるかどうかを調べます。
これはEric Lippert's restaurant metaphor(asyncのページで検索)で完全に説明されています。パンが焼かれるまで待つ代わりに、料理人は卵を茹で始めます。しかし、それはまだ同じ料理です。
非同期関数が待たずに呼び出されたコードを見ると、スレッドは待ち状態になるまで呼び出しを行い、何もせずに待機した後にステートメントを実行します。
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は私の呼び出し側が待ってまで、エフェクトコントロールは、戻って私の呼び出し元(まだ同じスレッド)に指定されています。
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のは別のスレッドで実行されます。その場合、制御は、あなたが積極的に、それを起動し、通常使用時に別のスレッドが関与しているだけの時間があるなどのawait
までの彼の呼び出し側に与えられ、 。 UIコントロールにアクセスする必要がある場合は、InvokeRequiredとInvokeが必要です。
非同期のawaitについてのもう一つの有用な物語:Stephen Cleary about async-await
(操作はI/Oデバイスからの応答を待っている間に自由メインスレッドに)ほとんどの場合 '非同期await'の目的は、I/O操作のためでした。あなたのケースでは、すべてのループで 'BackgroundWorker'と' ProgressChanged'を使用することを検討してください。 – Fabio