Асинхронные рабочие процессы в F#
Я программист C#, но у меня есть вопрос об Async Workflows в F#. Предположим, у меня есть следующий класс в библиотеке классов C#:
class File {
IAsyncResult BeginReadAll(string fileName, AsyncCallback callback, object state){}
string EndReadAll(IAsyncResult result){}
}
Насколько я понимаю, в F# для меня возможно создать функцию ReadAllAsync, которую я могу вызывать так:
async { let! rsp = ReadAllAsync() }
и что он не будет блокировать вызывающий поток, а скорее освободит его в пул потоков, а затем вернет в другой поток, когда операция завершится. Я думаю, что я понимаю, как кодировать это в F# с помощью Async.Primitive, но мой вопрос: могу ли я вызвать эту функцию ReadAllAsync из кода C#? Если да, как мне упаковать код F# в библиотеку классов для доступа из C#?
2 ответа
К счастью, когда прибудет Beta2, базовая библиотека F# будет иметь этот метод в модуле Async:
/// Return three functions that can be used to implement the .NET Asynchronous
/// Programming Model (APM) for a given asynchronous computation.
///
/// The functions should normally be published as members with prefix 'Begin',
/// 'End' and 'Cancel', and can be used within a type definition as follows:
/// <c>
/// let beginAction,endAction,cancelAction = Async.AsBeginEnd computation
/// member x.BeginSomeOperation(callback,state) = beginAction(callback,state)
/// member x.EndSomeOperation(iar) = endAction(iar)
/// member x.CancelSomeOperation(iar) = cancelAction(iar)
/// </c>
///
/// The resulting API will be familiar to programmers in other .NET languages and
/// is a useful way to publish asynchronous computations in .NET components.
static member AsBeginEnd : computation:Async<'T> -> // '
// The 'Begin' member
(System.AsyncCallback * obj -> System.IAsyncResult) *
// The 'End' member
(System.IAsyncResult -> 'T) * // '
// The 'Cancel' member
(System.IAsyncResult -> unit)
что облегчит написание вашего асинхронного кода с помощью F#, но затем опубликует его обратно на C# или VB, используя обычный APM.
Вот статья, которая показывает, что именно вы просите:
Тем не менее, вы в конечном итоге используете синтаксис C# монады. Поскольку LINQ был разработан для запросов, это выглядит немного странно. Кроме того, нет поддержки для try / catch или использования для утилизации.
"ReadAllAsync", который вы получаете от Async.BuildPrimitive, не будет обладать той же магией без правильного синтаксиса монады. Называть его достаточно просто, но настоящая полезность - это возможность его составить.
Вам, наверное, лучше просто использовать стиль C#, к сожалению,