非同期メソッドは待機中のスレッドをブロックしないためIO作業には適しているが、これは実際にどのように可能ですか?私は何かを完了するためにタスクをトリガするために聞いている必要がありますので、これはブロッキングがちょうど別の場所に移動されたことを意味ですか?async-awaitはどのようにブロックされませんか?
答えて
いいえ、ブロックは他の場所に移動されません。待ち状態の型を返すBCLメソッドは、I/O完了ポートとのオーバーラップI/Oなどの技術を使用して、完全に非同期のエクスペリエンスを実現します。
私はrecent blog postを持っています。これは、これがどのようにして物理的なデバイスまで戻ってきたかを説明しています。
実際にAsync-awaitがコードを書き直しています。それは、タスク継続を使用して、継続が作成されたときの現在の同期コンテキストにその継続を戻します。
したがって、次の機能
public async Task Example()
{
Foo();
string barResult = await BarAsync();
Baz(barResult);
}
がこの
がそれよりも今、その実際に多くの複雑なpublic Task Example()
{
Foo();
var syncContext = SyncronizationContext.Current;
return BarAsync().ContinueWith((continuation) =>
{
Action postback =() =>
{
string barResult = continuation.Result();
Baz(barResult)
}
if(syncContext != null)
syncContext.Post(postback, null);
else
Task.Run(postback);
});
}
(ただし、厳密に)のようなものにしてなったが、それは基本的な主旨で取得しますそれの。それが存在していて、何かもっとこの
public Task Example()
{
Foo();
var task = BarAsync();
var awaiter = task.GetAwaiter();
Action postback =() =>
{
string barResult = awaiter.GetResult();
Baz(barResult)
}
if(awaiter.IsCompleted)
postback();
else
{
var castAwaiter = awaiter as ICriticalNotifyCompletion;
if(castAwaiter != null)
{
castAwaiter.UnsafeOnCompleted(postback);
}
else
{
var context = SynchronizationContext.Current;
if (context == null)
context = new SynchronizationContext();
var contextCopy = context.CreateCopy();
awaiter.OnCompleted(() => contextCopy.Post(postback, null));
}
}
return task;
}
などはこれが正確に何が起こるかはまだありませんが、重要なことは奪うようにあれば、それが機能GetAwaiter()
を呼び出し、本当に起きているのである
awaiter.IsCompleted
がtrueの場合、すぐに戻るのではなく、ポストバックコードを同期して実行します。
クールなことは、あなたがいる限り、それはGetAwaiter()
と呼ばれる機能を有しており、返されるオブジェクトは、次のシグネチャ
public class MyAwaiter<TResult> : INotifyCompletion
{
public bool IsCompleted { get { ... } }
public void OnCompleted(Action continuation) { ... }
public TResult GetResult() { ... }
}
//or
public class MyAwaiter : INotifyCompletion
{
public bool IsCompleted { get { ... } }
public void OnCompleted(Action continuation) { ... }
public void GetResult() { ... }
}
に満たすことができるよう、あなたがタスクに待機する必要はありません、 await anythingことができています
making my wrong answer even more wrongの継続的な冒険では、コンパイラが私のexample関数をtoに変えた実際の逆コンパイルされたコードがここにあります。あなたがそこに目を通す場合
[DebuggerStepThrough, AsyncStateMachine(typeof(Form1.<Example>d__0))]
public Task Example()
{
Form1.<Example>d__0 <Example>d__;
<Example>d__.<>4__this = this;
<Example>d__.<>t__builder = AsyncTaskMethodBuilder.Create();
<Example>d__.<>1__state = -1;
AsyncTaskMethodBuilder <>t__builder = <Example>d__.<>t__builder;
<>t__builder.Start<Form1.<Example>d__0>(ref <Example>d__);
return <Example>d__.<>t__builder.Task;
}
は、今あなたがasync
を使用する場合、コンパイラは、実際にIAsyncStateMachine
インターフェイスに基づいてstate machineへのあなたの機能をオンためであるFoo()
、BarAsync()
、またはBaz(barResult)
への参照が存在しないでしょう。私たちが見に行く場合、コンパイラは新しい構造体が<Example>d__0
[CompilerGenerated]
[StructLayout(LayoutKind.Auto)]
private struct <Example>d__0 : IAsyncStateMachine
{
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
public Form1 <>4__this;
public string <barResult>5__1;
private TaskAwaiter<string> <>u__$awaiter2;
private object <>t__stack;
void IAsyncStateMachine.MoveNext()
{
try
{
int num = this.<>1__state;
if (num != -3)
{
TaskAwaiter<string> taskAwaiter;
if (num != 0)
{
this.<>4__this.Foo();
taskAwaiter = this.<>4__this.BarAsync().GetAwaiter();
if (!taskAwaiter.IsCompleted)
{
this.<>1__state = 0;
this.<>u__$awaiter2 = taskAwaiter;
this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter<string>, Form1.<Example>d__0>(ref taskAwaiter, ref this);
return;
}
}
else
{
taskAwaiter = this.<>u__$awaiter2;
this.<>u__$awaiter2 = default(TaskAwaiter<string>);
this.<>1__state = -1;
}
string arg_92_0 = taskAwaiter.GetResult();
taskAwaiter = default(TaskAwaiter<string>);
string text = arg_92_0;
this.<barResult>5__1 = text;
this.<>4__this.Baz(this.<barResult>5__1);
}
}
catch (Exception exception)
{
this.<>1__state = -2;
this.<>t__builder.SetException(exception);
return;
}
this.<>1__state = -2;
this.<>t__builder.SetResult();
}
[DebuggerHidden]
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine param0)
{
this.<>t__builder.SetStateMachine(param0);
}
}
と呼ばれる彼らのツールは、あなた自身を拡張し、コードから呼び出すことができますライブラリを使用させるためのオーバーILSpyの人々への感謝を生成しました。私がしなければならなかった上記のコードを得るには、
using System.IO;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using Mono.Cecil;
namespace Sandbox_Console
{
internal class Program
{
public static void Main()
{
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(@"C:\Code\Sandbox Form\SandboxForm\bin\Debug\SandboxForm.exe");
var context = new DecompilerContext(assembly.MainModule);
context.Settings.AsyncAwait = false; //If you don't do this it will show the original code with the "await" keyword and hide the state machine.
AstBuilder decompiler = new AstBuilder(context);
decompiler.AddAssembly(assembly);
using (var output = new StreamWriter("Output.cs"))
{
decompiler.GenerateCode(new PlainTextOutput(output));
}
}
}
}
- 1. ESIはブロックされているか、ブロックされていませんか?
- 2. renderer.render()はブロックされているか、ブロックされていませんか?
- 3. "dragenter"は子要素によってブロックされません。
- 4. ブロックされたスレッドによってプロセスがブロックされますか?なぜ、どのように?
- 5. CSS:ブロック要素の高さはどのように計算されますか?
- 6. 開始ブロックの値はどのように決定されますか?
- 7. Twitterのクリック・ハンドラーはどのようにしてブロックされますか?
- 8. オブジェクトは "with"ブロック内でどのようにインスタンス化されますか?
- 9. どのように$ブロック - > getChildHtml();データはMagento 2で渡されますか?
- 10. Hyperledgerトランザクションはブロック内でどのように注文されますか?
- 11. ExtJS MessageBoxは警告(..)のようにブロックしません
- 12. Robot.txtはブロックされていますが、何もブロックしていませんか?
- 13. TypeError: '>'は 'ブロック'と 'ブロック'のインスタンス間でサポートされていませんか?
- 14. どのようにこの構文は、Pythonで保持されませんか?
- 15. Facebookの更新はどのように更新されませんか?
- 16. Tryブロックの中には何も返されません
- 17. Windows OSはどのように逆コンパイルされていませんか?
- 18. オブジェクトはどのようにヌルと比較されませんか?
- 19. JOptionPaneはどのように同期されていませんか?
- 20. 削除されたブロックチェーンのブロックはどうなりますか?
- 21. どのようにしてBlockingQueueがブロックされていますか?
- 22. ブロック全体がナビゲーションバーに表示されていませんか?
- 23. ブロックされていないブロック:ブロックされていないタイプのエラー:ブロックできません。
- 24. ネストされた匿名ブロックのためにコードがコンパイルされませんか?
- 25. jinja2ブロックはテンプレートにレンダリングされません
- 26. Clojure catchブロックをより機能的に再帰させるにはどうすればよいですか?
- 27. xmlの空ノードタグはどのように解釈され、ノードの存在は解釈されませんか?
- 28. write()関数はCでブロックされているか、ブロックされていませんか?
- 29. 私のデータはどのようにサーバに表示されますが、クライアントブラウザには表示されません
- 30. Simulinkブロックをどのように反転させるのですか?
クール!私がこの質問を考えたとき、あなたのブログを実際に読んでいたのは面白いです。私は再びstackoverflowに行く前にすべてのあなたのポストを読む必要がありますように見えます! – NickL
@NickL、あなたは一人ではありません。:) –