Как мне ссылаться на текущий экземпляр в c'or в F #? - PullRequest
1 голос
/ 21 марта 2012

Вопросы (3 из них связанных) выделены жирным шрифтом ниже.

Я пытаюсь создать класс F # - мне нужно использовать его, не ссылаясь на сборку F # из C #.

У меня есть такой код:

type ReceiverExceptionEventArgs(ex:Exception) =
    inherit EventArgs()
    member this.Exception = ex

type ExceptionRaised = delegate of obj * ReceiverExceptionEventArgs -> unit

type Receiver( ... ) =

  let error  = new Event<ExceptionRaised, ReceiverExceptionEventArgs>()

  let a = new Actor<...>(fun inbox -> ...)   

  [<CLIEvent>]
  member __.Error = error.Publish

  /// Starts the receiver which starts the consuming from the service bus
  /// and creates the queue if it doesn't exist
  member x.Start () =
    logger.InfoFormat("start called for queue '{0}'", desc)
    a.Post Start

Я хотел бы добавить это после let a = new Actor...:

do a.Error.Add(fun ex -> error.Trigger(this, new ReceiverExceptionEventArgs(ex)))

Но я нев вышеприведенной строке нет ссылки на 'this' ... Как бы я сделал это идиоматически в F #?

Как еще одно осложнение, актер начинает числоасинхронных вычислений, которые в основном являются циклами;эти вычисления возвращают единицу, поэтому я не могу просто сделать:

let startPairsAsync pairs token =
  async {
    for Pair(mf, rs) in pairs do
      for r in rs do 
        match Async.Start(Async.Catch(r |> worker), token) with
        | Choice1Of2 () -> ()
        | Choice2Of2 ex -> error.Trigger(null, new ReceiverExceptionEventArgs(ex)) }

, потому что worker r равно Async<unit>, поэтому Я получаю This expression was expected to have type 'unit' but was here 'Choice1of2<'a, 'b>' при первом совпадении с образцом.


Отступление:

Является ли идея, что я создаю актеров также для каждого работника?Я хотел бы иметь код, который похож на то, как erlang делает «супервизоры», потому что то, с чем я работаю, может произойти сбой произвольно почти в любой точке (сети) ... Супервизоры выходят за рамки этого вопроса;но получу ли я лучшую обработку идиоматических исключений с Mutliple Actors, а не с Async.Catch?

Ответы [ 2 ]

4 голосов
/ 21 марта 2012

Относительно this, используйте

type MyClass(args) as this =

в объявлении для связывания this внутри конструктора. (Вы можете использовать любой идентификатор, который вам нравится.)

(см. Также

http://lorgonblog.wordpress.com/2009/02/13/the-basic-syntax-of-f-classes-interfaces-and-members/

)

2 голосов
/ 22 марта 2012

Относительно вашего второго вопроса, касающегося асинхронного рабочего процесса, я не до конца понимаю ваш код, но если вы пытаетесь запустить некоторые асинхронные вычисления и обрабатывать исключения, которые могут возникнуть при их выполнении, использовать намного проще try ... with внутри асинхронного рабочего процесса вместо Async.Catch. Примерно так может быть лучше:

let startPairsAsync pairs token = 
  let work = 
    [ for Pair(mf, rs) in pairs do 
        for r in rs do  
          // Produce asynchronous computation that is 
          // protected using a try .. with block
          yield async { 
            try do! worker r 
            with e -> error.Trigger(null, new ReceiverExceptionEventArgs(ex)) } ]
    // Compose them to run all computations in parallel
    |> Async.Parallel

  // Run composed computation with a cancellation token
  Async.Start(work, token)
...