2016-05-19 4 views
1

私はこのような方法があります:私はちょうどそのコードを呼び出しせずに、直接dataGridView1.SelectedRowsにアクセスしてるされ、それがうまく働いてnoticied非同期メソッドからDataGridView.SelectedRowsにアクセスするためにinvokeが必要ですか?

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

:このように呼ばれる

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

を。無効な操作を行っていますか?これは動作するはずか、ここで呼び出す必要がありますか?

+0

(操作はI/Oデバイスからの応答を待っている間に自由メインスレッドに)ほとんどの場合 '非同期await'の目的は、I/O操作のためでした。あなたのケースでは、すべてのループで 'BackgroundWorker'と' ProgressChanged'を使用することを検討してください。 – Fabio

答えて

1

公式の答えは、あなたの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

+0

偉大な答え、ありがとう – Jack

0

新しいスレッド/ BackgroundWorkerを作成するのではなく、asyncawaitを使用するからです。 私の意見では、Controlsとやり取りするときにInvokeを使用することは決して悪いことではありません。

+0

新しいスレッド/ backgroundWorkerを作成しないと、外部スレッドでコードを実行してから、invokeを使用する必要がありますか?私はそれが悪いと思う、私はコントロールと対話するときInvokeの代替を見つけることができませんでした – Jack

+0

はい、それは... by:await Task。「 { foo(); });「 は非同期ではないですか? – Essigwurst

+0

'await Task.Run(foo());'を使用するとUIがブロックされ、**呼び出しを使用する必要があります**。 – Essigwurst

関連する問題