Npgsql事件处理和并发

时间:2015-09-22 05:48:40

标签: multithreading f# npgsql

我想将现有的事件实现替换为可以在必要时同时处理事件的事件。不幸的是我之前从未实现过任何类型的并发,但必须从某个地方开始呃?

我一直在阅读Functional Reactive Programming。尽管看起来相对简单,但我对如何将这些示例应用到我的应用程序中感到困惑。事实上,我甚至不确定这是否是最适合实现并发的方法。

我还能以某种方式利用任务并行库(TPL),因为它提供了线程管理,那么我不需要过多担心产生太多线程。遗憾的是,上述链接中的示例不包含使用TPL的任何内容。

我目前的代码如下。我仍然是一个新手程序员,需要一些手握才能通​​过。为麻烦道歉。 :(

open System
open System.Threading
open Npgsql

// This application is a Windows service. PostgreSQL sends a notice whenever a new row has been added to a table. 

// The next function processes new rows, aka tasks.
let private processTask () =
    EventLog.writeEventLog "Information" "Received new task notification."
    // Task processing yet to be implemented.

// A connection to PostgreSQL that stays open while service is running. Receives notifications.
let newNotifyConnection (host : string, username : string, password : string, database : string) = 
    let connectionString = sprintf "Host=%s;Username=%s;Password=%s;Database=%s;ContinuousProcessing=true;Keepalive=120;CommandTimeout=0" host username password database
    new NpgsqlConnection(connectionString)

let private notifyConnection = newNotifyConnection Settings.npgsqlConnection
let private listen = new NpgsqlCommand("LISTEN newtask", notifyConnection)

// Event for receiving and processing notifications.
let private onNotification (sender : obj) (e : NpgsqlNotificationEventArgs) =
    processTask()

let private notificationEventHandler = new NotificationEventHandler(onNotification)

// Run this function when service starts.
let startWorker () =
    notifyConnection.Notification.AddHandler(notificationEventHandler)
    notifyConnection.Open()
    listen.ExecuteNonQuery() |> ignore

// Run this function when service stops.
let stopWorker () =
    listen.Dispose()
    notifyConnection.Dispose()

1 个答案:

答案 0 :(得分:2)

如果您愿意首先使用F#进行功能编程路线而且我建议安装可从Nuget获得的FSharp.Control.Reactive。这将使得使用RX变得更加容易,包括向Observable模块添加更多方法(默认情况下,F#只包含一个子集)。

对我来说,代码中的关键方法如下所示,因为这是将回调链接到事件源的方法。

let startWorker () =
    notifyConnection.Notification.AddHandler(notificationEventHandler)
    notifyConnection.Open()
    listen.ExecuteNonQuery() |> ignore

诀窍是给你的notifyConnection对象一个回调对象,RX为你提供了在Npgsql库和RX框架之间桥接世界的可能性。

类似的东西:

open System
open System.Reactive.Linq

let observableCreate subscriptionFunction = Observable.Create(new Func<_, IDisposable>(subscriptionFunction))

let sourceObservable = observableCreate  (fun observer -> 
    // Your notifyConnection object will now direct all events to the observer provided
    notifyConnection.Notification.AddHandler(observer.OnNext)
    notifyConnection.Open()
    listen.ExecuteNonQuery() |> ignore
    // RX includes the CompositeDisposable class which you can also use
    { new IDisposable with 
          x.Dispose() =
              listen.Dispose()
              notifyConnection.Dispose() })

use subscription = sourceObservable.Subscribe(notifyConnectionHandler)

请注意,FSharp.Control.Reactive Nuget包提供了Observable.create函数。 (编辑:已经指出Reactive包没有Observable.Create的包装器所以我自己定义了它)。

以上将(订阅时 - 使用Subscribe()方法): - 打开连接 - 执行查询 - 创建一个在处理订阅时使用的一次性用品。

更有趣的是,您可以使用Observable模块中的方法链接observable并将其与其他人组合,从而允许您创建被动程序。如果你有兴趣在F#中使用IEvent的/ IObservable,那么读RX可能是明智的。