C#にTask
はConfigureAwait(false)
、(たとえば) 必ずしも必要ではない UI スレッドへの同期を防止するためのライブラリがあります
。
.NET では、 は 1 つしか存在できないと考えているSynchonizationContext
ため、どのスレッドプールでTask
継続を実行するかは明確です。
ライブラリの場合、ユーザーが webrequest (.NETHttpContext.Current.Items
フロー)、コマンドライン (通常のマルチスレッド)、XAML/Windows フォーム (単一の UI スレッド) にいると想定できない場合は、ほとんどの場合、 を使用する方がよいConfigureAwait(false)
ため、Waiter は知っています。ウェイターを呼び出すために使用されているスレッドで継続を実行することができます(これは、初期ワークロードが開始されたスレッドプールでスレッド枯渇につながる可能性のあるライブラリ内のコードをブロックする場合にのみ悪いことです。そうしないでください)。
ポイントは、ライブラリの観点からは、継続を同期するために呼び出し元のスレッドプールのスレッドを使用したくないということです。継続を任意のスレッドで実行したいだけです。これにより、コンテキスト スイッチが節約され、たとえば UI スレッドの負荷が維持されます。
ExecutionContext
Scala では、Future の各操作 (つまり、マップ) には(暗黙的に渡される) が必要です。TaskFactory
これにより、スレッドプールの管理が非常に簡単になります。これは、.NET のやや奇妙な's (誰も使用していないようで、デフォルトを使用しているだけです)よりもはるかに気に入っていますTaskFactory
。
私の質問は、コンテキスト スイッチが不要な場合があるという点で、Scala には .NET と同じ問題がありConfigureAwait
ますか?
私がこれについて疑問に思っているScalaで見つけた具体的な例:
def trace[T](message: => String)(block: => Future[T]): Future[T] = {
if (!logger.isTraceEnabled) block
else {
val startedAt = System.currentTimeMillis()
block.map { result =>
val timeTaken = System.currentTimeMillis() - startedAt
logger.trace(s"$message took ${timeTaken}ms")
result
}
}
}
私は play を使用しており、通常は play のデフォルトの Implicit をインポートしますExecutionContext
。上のマップはblock
、実行コンテキストで実行する必要があります。
この Scala の部分をライブラリーに記述し、暗黙のパラメーターを追加するとしますexecutionContext
。
def trace[T](message: => String)(block: => Future[T])(implicit executionContext: ExecutionContext): Future[T] = {
ライブラリにplay のデフォルトをインポートする代わりにExecutionContext
。