> в Future<'a>
+let join = Future.join (Future.ready (Future.ready 12))
+
+// Ловит исключение вложенной Future, возвращает Result<'a, exn>
+let catch = Future.catch (Future.lazy (fun () -> failwith "exception"))
+```
+
+
+Future это уже объект машины состояний. По этой причине множественное использование
+(комбинирование или запуск) одного экземпляра Future недопустимы.
+То есть следующий код, запускающий fut дважды недопустим
+```fsharp
+let fut = someAsyncWork ()
+let doubleFut = fut |> Future.bind (fun () -> fut)
+```
+Вместо этого всегда пересоздавайте Future при необходимости двойного использования:
+```fsharp
+let doubleFut = someAsyncWork () |> Future.bind (fun () -> someAsyncWork ())
+```
+
+
+
+## Использование Future CE
+
+Future имеет свой CE, который используется также как async или task CE встроенные в F#.
+Более подробно о CE вы можете прочитать на [сайте](https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions).
+
+Например, мы можем заменить базовые функции создания на future CE:
+```fsharp
+let ready = future { return "Hello, world!" } // ~ Future.ready "Hello, world!"
+let lazy' = future { return (foo ()) } // ~ Future.lazy' (fun () -> foo ())
+```
+
+Наиболее важным свойством CE является упрощение работы с bind.
+Пример чтения-записи можно переписать используя CE так:
+
+```fsharp
+// readFileAsync: filePath: string -> Future
+// writeFileAsync: filePath: string -> content: string -> Future
+let readAndWriteFuture = futur {
+ let! content = readFileAsync "my-file.txt"
+ return! writeFileAsync "other-file.txt" content
+}
+```
+
+Видимым преимуществом CE является возможность "уплощить" цепочка bind, зависимых между собой.
+Пример множественно зависимых bind можно переписать так:
+
+```fsharp
+let doManyWorkWithCrossResults = future {
+ let! val1 = doWork1 ()
+ let! val2 = doWork2 val1
+ let! val3 = doWork3 val1 val2
+ ...
+ let! valN = doWorkN val1 val2 ... valPrevN
+}
+```
+
+Также CE добавляют синтаксис и для Future.merge или Future.catch комбинаторов.
+
+```fsharp
+let parallelCE = future {
+ let! val1 = doWork1 ()
+ and! val2 = doWork2 ()
+ and! val3 = doWork3 ()
+}
+```
+
+```fsharp
+let catchCE = future {
+ try
+ do! doWork ()
+ with ex ->
+ printfn $"{ex}"
+}
+```
+
+```fsharp
+let tryFinally = future {
+ try
+ do! doWork ()
+ finally
+ do finallize ()
+}
+```
+
+
+## Преобразование из Async и Task
+
+Существующие Async и Task можно преобразовать в Future и использовать результат их работы.
+Исходные Async и Task будут запущены на своих родных системах запуска, но их результат будет
+передан через возвращенную Future.
+
+```fsharp
+let asyncToFuture = Future.ofAsync (async { ... })
+let taskToFuture = Future.ofTask (task { ... })
+```
+
+Возможны и обратные преобразования. При этом Future будут запущены на механизме запуска
+соответствующего примитива при запуске этого примитива.
+
+```fsharp
+let futureToAsync = Future.ofAsync (async { ... })
+let futureToTask = Future.ofTask (task { ... })
+```
+
+
+## Ручная реализация Future
+
+Future это всего-лишь интерфейс с методами Poll и Drop.
+Можно создать свою Future просто реализовав их.
+
+Ручная реализация Future корректным образом не такая тривиальная задача,
+требующая ручной реализации конечного или не очень автомата.
+Поэтому не рекомендуется делать это, только если Вы не разрабатываете
+API для использования механизма асинхронности на низком уровне.
+
+Объяснения и более подробные примеры следует искать в более продвинутых главах.
+
+
diff --git a/docs/ru/basics/running.md b/docs/ru/basics/running.md
new file mode 100644
index 0000000..7415843
--- /dev/null
+++ b/docs/ru/basics/running.md
@@ -0,0 +1,53 @@
+# Запуск Future
+
+
+## Запуск на текущем потоке
+
+Future можно запустить на текущем потоке используя `Future.runBlocking`.
+Переданная Future запустится, а вызывающий поток будет заблокирован
+пока не получится результат.
+```fsharp
+let fut = future {
+ let! name = Future.ready "Alex"
+ do! Future.sleepMs 1000
+ return $"Hello, {name}!"
+}
+
+let phrase = fut |> Future.runBlocking
+printfn $"{phrase}"
+```
+
+
+## Запуск используя Runtime
+
+Future можно запустить на Runtime.
+Runtime это планировщик для нескольких параллельно выполняющихся Future,
+не используя Future.merge и снимая его ограничения
+(Future скомбинированные используя Future.merge никогда не выполняются по-настоящему параллельно).
+
+Запустить Future на планировщике можно используя его метод Spawn.
+
+```fsharp
+let fut = future { ... }
+let fTask = ThreadPoolRuntime.Instance.Spawn(fut)
+```
+
+Spawn возвращает объект запущенной задачи (IFutureTask<'a>).
+Используя экземпляр запущенной задачи можно преобразовать её в ожидающую выполнения
+Future используя Await, или прервать её выполнение через Abort.
+Если задача была прервана, ожидающая Future выбросит исключение при своем запуске.
+
+```fsharp
+future {
+ let fTask = ThreadPoolRuntime.Instance.Spawn(future { ... })
+ do! doOtherWork ()
+ let! fTaskResult = fTask.Await()
+}
+```
+
+
+IFutureTask.Await может быть вызван только один раз.
+
+
+По-умолчанию Await создает Future, вызывающую Abort при своем Drop.
+Это можно переопределить вызвав Await с флагом background=true (`fTask.Await(true)`).
diff --git a/src/FSharp.Control.Futures/Future.fs b/src/FSharp.Control.Futures/Future.fs
index dddc0ea..5dae0d8 100644
--- a/src/FSharp.Control.Futures/Future.fs
+++ b/src/FSharp.Control.Futures/Future.fs
@@ -275,6 +275,11 @@ module Future =
|> inspect (fun _ -> do finalizer ())
|> map (fun x -> match x with Ok r -> r | Error ex -> raise ex)
+ // let inline tryFinallyM (body: Future<'a>) (finalizer: unit -> Future): Future<'a> =
+ // catch body
+ // |> inspectM (fun _ -> finalizer ())
+ // |> map (fun x -> match x with Ok r -> r | Error ex -> raise ex)
+
/// Creates a Future that returns control flow to the runtime once
/// Future that returns control flow to the runtime once
let inline yieldWorkflow () : Future =
@@ -338,6 +343,9 @@ type FutureBuilder() =
member inline _.TryFinally(body: unit -> Future<'a>, finalizer: unit -> unit): Future<'a> =
Future.tryFinally (Future.delay body) finalizer
+ // member inline _.TryFinally(body: unit -> Future<'a>, finalizer: unit -> Future): Future<'a> =
+ // Future.tryFinallyM (Future.delay body) finalizer
+
member inline _.Using<'d, 'a when 'd :> IDisposable>(disposable: 'd, body: 'd -> Future<'a>): Future<'a> =
let body' = fun () -> body disposable
let disposer = fun () ->
diff --git a/src/FSharp.Control.Futures/Transforms.fs b/src/FSharp.Control.Futures/Transforms.fs
index d4966f8..6fa00e0 100644
--- a/src/FSharp.Control.Futures/Transforms.fs
+++ b/src/FSharp.Control.Futures/Transforms.fs
@@ -158,8 +158,8 @@ module FutureApmTransforms =
let ctx =
{ new NotFeaturedContext() with
override this.Wake() =
- if asyncResult.IsCompleted then invalidOp "Cannot call Wait when Future is Ready"
- startPollOnContext this }
+ if not asyncResult.IsCompleted then
+ startPollOnContext this }
startPollOnContext ctx