2015-05-10 2 views
4

Я пытаюсь заставить приведенный ниже код работать в рабочем процессе F # async, но я получаю сообщение об ошибке «Неожиданный символ» в выражении. Я довольно новичок как в F #, так и в async вообще. Что мне здесь не хватает.Запуск C# async method в f # workflow

let someFunction (req : HttpRequestMesssage) a b = 

    // code 
    async{ 
     let! readToProvider = 
      req.Content.ReadAsMultipartAsync(provider) 
      |> Async.AwaitIAsyncResult 

    } |> Async.RunSynchronously 

    req.CreateResponse(HttpStatusCode.OK) 

ответ

6

Я беспокоюсь, что мой предыдущий ответ был не совсем то, что вы хотите. То, что я поставил, просто вызвало ошибку компиляции. Но одна вещь об этом заключается в том, что он не работает асинхронно. Task.Wait и Async.RunSynchronously будут блокировать бегущую нить до завершения операции.

Если вы хотите на самом деле быть асинхров, т.е. не блокирует, вы должны поместить весь метод, или, по крайней мере, последняя часть его, в async блок, таким образом, что вы на самом деле возвращающий async ора вызывающему абоненту. Таким образом, ответ будет

let someFunction (req : HttpRequestMesssage) a b = 
    async { 
    let! readToProvider = (req.Content.ReadAsMultipartAsync provider) |> Async.AwaitIAsyncResult 
    return req.CreateResponse HttpStatusCode.OK 
    } 

Это опция возвращает не ответ, но Async<Response>. Итак, теперь вызывающий может решить, как его запускать, блокируя или по-настоящему асинхронно.

Таким образом, если вы используете веб-сервер, который обрабатывает асинхронные запросы, то вы можете просто подключить эту функцию к конечной точке (возможно преобразование Async в Task в точке подключения, так как большинство веб-серверов .net асинхронными написаны с точки зрения C#), и он будет выполняться асинхронно, не блокируя поток. Или, если вы вызываете его из другого async op, вы можете сделать do! someFunction ..., и он будет выполняться асинхронно. Но если вызывающему пользователю все равно, и он просто хочет работать синхронно, он может сделать someFunction ... |> Async.RunSynchronously. Таким образом, вы получаете большую гибкость. И вы всегда можете определить let someFunctionSync ... = someFunction ... |> Async.RunSynchronously, если это более распространенный вариант использования.

Я бы рекомендовал пройти этот путь, если вы действительно не хотите применять блокировку.

5

Вы делаете это правильно. Вы получаете ошибку только потому, что закончили свой async блок с выражением let!. Измените его на return!, или do! ... |> Async.Ignore, и все будет хорошо.

Блоки в F # (ни рабочие процессы, ни обычные кодовые блоки) не должны заканчиваться let.

Конечно, если все вы действительно делать в рабочем процессе является то, что один вызов, вам не нужен блок рабочего процесса на всех (вы никогда не должны нуждаться, чтобы написать блок для одного вызов). Просто сделайте

req.Content.ReadAsMultipartAsync provider 
    |> Async.AwaitIAsyncResult 
    |> Async.Ignore 
    |> Async.RunSynchronously 
req.CreateResponse HttpStatusCode.OK 

Или по этому вопросу, просто использовать встроенный в задачах Погоди, который делает то же самое, как Async.RunSynchronously:

(req.Content.ReadAsMultipartAsync provider).Wait() 
Смежные вопросы