Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parallel processing 与throttle并行的异步函数调用_Parallel Processing_F#_Queue_Message Queue_Throttling - Fatal编程技术网

Parallel processing 与throttle并行的异步函数调用

Parallel processing 与throttle并行的异步函数调用,parallel-processing,f#,queue,message-queue,throttling,Parallel Processing,F#,Queue,Message Queue,Throttling,我已经根据建议进行了尝试,但仍然有打嗝的问题,有人可以根据尝试提供帮助吗?我的方法签名在返回元组时是不同的,我需要将结果返回给调用者(不仅仅是执行) 这一行我有错误do!工作 错误:表达式应具有类型结果,但此处具有类型“unit” 类型错误={ 代码:int 消息:string } ///代理使用的消息类型-包含排队 ///工程项目的验收和完工通知 键入内部节流消息= |完成了结果分析 |异步排队 ///表示在中同时运行操作的代理。号码是什么时候 ///超过“限制”的并发操作数,它们将排队并稍后

我已经根据建议进行了尝试,但仍然有打嗝的问题,有人可以根据尝试提供帮助吗?我的方法签名在返回元组时是不同的,我需要将结果返回给调用者(不仅仅是执行)

这一行我有错误
do!工作

错误:表达式应具有类型结果,但此处具有类型“unit”

类型错误={
代码:int
消息:string
}
///代理使用的消息类型-包含排队
///工程项目的验收和完工通知
键入内部节流消息=
|完成了结果分析
|异步排队
///表示在中同时运行操作的代理。号码是什么时候
///超过“限制”的并发操作数,它们将排队并稍后处理
设节流剂极限=
MailboxProcessor.Start(有趣的收件箱->
异步的{
//代理主体未并行执行,
//因此,我们可以安全地使用可变队列和计数器
让queue=System.Collections.Generic.queue()
让运行=参考0
尽管如此
//将新工作项排队或减少计数器
//有多少任务在后台运行
let!msg=inbox.Receive()
配味精
|已完成r->decr运行
|排队w->queue.Enqueue(w)
//如果我们有少于极限&还有一些工作要做
//做,然后在后台开始工作!
运行时.Value0 do
let work=queue.Dequeue()
递增运行
do!//工作完成后,发送“已完成”
//返回代理以释放插槽
异步的{
干!干
收件箱.邮件(已完成)
}
|>Async.StartChild
|>异步。忽略
})
让requestAsync(url:string):异步=
异步的{
Console.WriteLine(“模拟请求”+url)
尝试
do!Async.Sleep(1000)
返回Ok(url+“:body…”)
使用:?WebException作为e->
返回错误{code=500;message=“内部服务器错误”;}
}
让URL=[|
"http://www.example.com/1";
"http://www.example.com/2";
"http://www.example.com/3";
"http://www.example.com/4";
"http://www.example.com/5";
"http://www.example.com/6";
"http://www.example.com/7";
"http://www.example.com/8";
"http://www.example.com/9";
|]
设w=节流剂3
对于url中的url,请执行以下操作:
请求异步url
|>排队
|>w.邮政

我认为问题在于您试图修改代理,使工作项不是
异步的,即运行和完成时不返回结果的操作,而是实际返回内容的操作。你可以这样做,但你必须决定你想对结果做什么

在这种情况下,我认为让代理保持原样更容易,而是在最后处理结果的收集。例如,如果要在集合中收集它们,可以编写:

let results = System.Collections.Concurrent.ConcurrentBag<_>()
let w = throttlingAgent 3
for url in urls do
  async { 
    let! res = requestAsync url
    results.Add res } |> Enqueue |> w.Post
let results=System.Collections.Concurrent.ConcurrentBag()
设w=节流剂3
对于url中的url,请执行以下操作:
异步{
let!res=requestAsync url
结果.添加res}|>Enqueue}>w.Post
为完整起见,这使用了以下类型和代理的定义:

type Error = {
  code : int
  message : string
}

/// Message type used by the agent - contains queueing
/// of work items and notification of completion
type ThrottlingAgentMessage =
  | Completed 
  | Enqueue of Async<unit>

/// Represents an agent that runs operations in concurrently. When the number
/// of concurrent operations exceeds 'limit', they are queued and processed later
let throttlingAgent limit =
  MailboxProcessor.Start(fun inbox ->
    async {
      // The agent body is not executing in parallel,
      // so we can safely use mutable queue & counter
      let queue = System.Collections.Generic.Queue<Async<unit>>()
      let running = ref 0

      while true do

        // Enqueue new work items or decrement the counter
        // of how many tasks are running in the background
        let! msg = inbox.Receive()
        match msg with
        | Completed -> decr running
        | Enqueue w -> queue.Enqueue(w)

        // If we have less than limit & there is some work to
        // do, then start the work in the background!
        while running.Value < limit && queue.Count > 0 do
          let work = queue.Dequeue()
          incr running
          do! // When the work completes, send 'Completed'
              // back to the agent to free a slot
              async {
                do! work
                inbox.Post(Completed)
              }
              |> Async.StartChild
              |> Async.Ignore
    })

let requestAsync (url: string) : Async<Result<string, Error>> =
    async {
        Console.WriteLine ("Simulating request " + url)
        try
            do! Async.Sleep(1000)
            return Ok (url + ":body...")
        with :? WebException as e ->
            return Error {code = 500; message = "Internal Server Error";}
    }
类型错误={
代码:int
消息:string
}
///代理使用的消息类型-包含排队
///工程项目的验收和完工通知
键入ThrottlingAgentMessage=
|完成
|异步排队
///表示在中同时运行操作的代理。号码是什么时候
///超过“限制”的并发操作数,它们将排队并稍后处理
设节流剂极限=
MailboxProcessor.Start(有趣的收件箱->
异步的{
//代理主体未并行执行,
//因此,我们可以安全地使用可变队列和计数器
让queue=System.Collections.Generic.queue()
让运行=参考0
尽管如此
//将新工作项排队或减少计数器
//有多少任务在后台运行
let!msg=inbox.Receive()
配味精
|已完成->decr正在运行
|排队w->queue.Enqueue(w)
//如果我们有少于极限&还有一些工作要做
//做,然后在后台开始工作!
运行时.Value0 do
let work=queue.Dequeue()
递增运行
do!//工作完成后,发送“已完成”
//返回代理以释放插槽
异步的{
干!干
收件箱.邮件(已完成)
}
|>Async.StartChild
|>异步。忽略
})
让requestAsync(url:string):异步=
异步的{
Console.WriteLine(“模拟请求”+url)
尝试
do!Async.Sleep(1000)
返回Ok(url+“:body…”)
使用:?WebException作为e->
返回错误{code=500;message=“内部服务器错误”;}
}

Hi Taylor的可能副本,我将在此基础上尝试并发布一些编辑以供可能的审阅,请修复我的特定签名有问题
Async
,而解决方案有不同的签名。您可以审阅我的签名吗attempt@TaylorWood我认为这不是复制品。OP试图修改前面的答案,做一些不同的事情。谢谢Tomas。问题,这是一个长期运行的过程吗<代码>为true时执行
。我要测试和研究这个。如果它是一个持续长时间运行的过程,那么我需要进一步定制它,以便在
type Error = {
  code : int
  message : string
}

/// Message type used by the agent - contains queueing
/// of work items and notification of completion
type ThrottlingAgentMessage =
  | Completed 
  | Enqueue of Async<unit>

/// Represents an agent that runs operations in concurrently. When the number
/// of concurrent operations exceeds 'limit', they are queued and processed later
let throttlingAgent limit =
  MailboxProcessor.Start(fun inbox ->
    async {
      // The agent body is not executing in parallel,
      // so we can safely use mutable queue & counter
      let queue = System.Collections.Generic.Queue<Async<unit>>()
      let running = ref 0

      while true do

        // Enqueue new work items or decrement the counter
        // of how many tasks are running in the background
        let! msg = inbox.Receive()
        match msg with
        | Completed -> decr running
        | Enqueue w -> queue.Enqueue(w)

        // If we have less than limit & there is some work to
        // do, then start the work in the background!
        while running.Value < limit && queue.Count > 0 do
          let work = queue.Dequeue()
          incr running
          do! // When the work completes, send 'Completed'
              // back to the agent to free a slot
              async {
                do! work
                inbox.Post(Completed)
              }
              |> Async.StartChild
              |> Async.Ignore
    })

let requestAsync (url: string) : Async<Result<string, Error>> =
    async {
        Console.WriteLine ("Simulating request " + url)
        try
            do! Async.Sleep(1000)
            return Ok (url + ":body...")
        with :? WebException as e ->
            return Error {code = 500; message = "Internal Server Error";}
    }