async/await
についてもう少し理解しています。特に、async
メソッドとawait
でコンパイラが「一時停止」する方法を知っていると、追加のスレッドが生成されません。一例として、C#コンパイラは、非同期メソッドをいつ切断するかを知っていますか?
、私は私の方法は、「一時停止」を取得しますし、それを呼び出したスレッドは、スレッドプールへとTask
いったん戻り、await sqlConnection.OpenAsync();
があることを知っているのは、私が
DoSomeStuff();
await sqlConnection.OpenAsync();
DoSomeOtherStuff();
ようasync
方法を持っているとしましょうつまり、接続の開始を追跡すると、使用可能なスレッドがDoSomeOtherStuff()
を実行していることがわかります。
| DoSomeStuff() | "start" opening connection | ------------------------------------ |
| ---------------------------------------------------------- | DoSomeOtherStuff() - |
ここで私は混乱するところです。私はOpenAsync
(https://referencesource.microsoft.com/#System.Data/System/Data/Common/DBConnection.cs,e9166ee1c5d11996,references)のソースコードを見て、それは私が仕事を外部リソースとの通信を開始しているため、コンパイラは、スレッドを「断つ」ことを知っているだろういくつかの場所を見て想像し
public Task OpenAsync() {
return OpenAsync(CancellationToken.None);
}
public virtual Task OpenAsync(CancellationToken cancellationToken) {
TaskCompletionSource<object> taskCompletionSource = new TaskCompletionSource<object>();
if (cancellationToken.IsCancellationRequested) {
taskCompletionSource.SetCanceled();
}
else {
try {
Open();
taskCompletionSource.SetResult(null);
}
catch (Exception e) {
taskCompletionSource.SetException(e);
}
}
return taskCompletionSource.Task;
}
だが、私は実際にそれを見ていない、そして実際には、Open();
はそれが同期的に待っていることを暗示しているようです。誰かがこれがスレッドレスの「真の非同期」コードになる方法を説明できますか?
このようなOpenAsyncの実装は、実際には「真の非同期」コードではありません。 – CodeFuller
C#コンパイラはコードを書き直すと、隠しクラスの* 2つのメソッドに変わります。 DoSomeOtherStuff()呼び出しは2番目のメソッドにあります。あなたが持っていて、両方の部分で使われているローカル変数は、そのクラスのフィールドになります。 ildasm.exeユーティリティを使って見ることができます。 –
@CodeFuller OpenAsync()の "真の非同期"実装の例を教えてください。あるいは、上記の 'OpenAsync()'がどのように真のasyncになるのかを示すことができますか? – Questionaire