尽可能简单:
试图采用“合法”的方式:
如何创建每个从函数返回字符串的任务/操作的队列(FIFO)?
2014-06-21更新
这就是我现在所处的位置。我可以在ConcurrentQueue上创建任务。
问题仍然是如何修改它以允许创建/调用任务,任务放入FIFO队列,以及任务的结果(String)返回到调用它的变量,如:
昏暗的结果=任务......(“命令”)......
以下是我测试方法的基础(编译和运行):
Dim TCQ As New ConcurrentQueue(Of Task)
Sub Main()
' This simulates program calls to Enqueue tasks on TCQ:
For i = 1 To 20
TCQ.Enqueue(GetTask(Date.Now.ToLongTimeString & " - Command number " & i))
Next
' normally, TCQ would be watched in a loop
Do While TCQ.Count > 0
Dim tsk As Task = Nothing
TCQ.TryDequeue(tsk)
tsk.Wait()
Console.WriteLine(Date.Now.ToLongTimeString & " [" & tsk.Id & "] post-Wait(): " & tsk.Id & " TCQ.Count: " & TCQ.Count)
Loop
Console.WriteLine("done.")
Console.ReadLine()
End Sub
下一个函数创建一个包含命令字符串的任务...
Function GetTask(CommandString As String) As Task(Of String)
Dim t As Task(Of String) = Nothing
Dim cts As New CancellationTokenSource()
Dim ct As CancellationToken = cts.Token
Try
t = Task(Of String).Factory.StartNew(Function()
Return GetCommandResults(CommandString, ct)
End Function, ct, TaskCreationOptions.LongRunning)
t.Wait()
Console.WriteLine("GetTask.Id: " & t.Id & " result: " & t.Result)
Catch ex As Exception
Console.WriteLine("Caught Exception: " & ex.ToString)
End Try
Return t
End Function
此功能用于将命令发送到设备,并将响应存储为字符串......
Function GetCommandResults(theCommand As String, ct As CancellationToken) As String
Console.WriteLine(String.Format("--> starting GetCommandResults({0})", theCommand))
Thread.Sleep(2000)
Console.WriteLine(String.Format("<-- done with GetCommandResults({0})", theCommand))
Return String.Format(Date.Now.ToLongTimeString & " - GetCommandResults returned {0}", theCommand)
End Function
收益率:
[Main()] before creating tasks
--> starting GetCommandResults(8:14:38 PM - Command number 1)
<-- done with GetCommandResults(8:14:38 PM - Command number 1)
GetTask.Id: 1 result: 8:14:40 PM - GetCommandResults returned 8:14:38 PM - Command number 1
--> starting GetCommandResults(8:14:40 PM - Command number 2)
<-- done with GetCommandResults(8:14:40 PM - Command number 2)
GetTask.Id: 2 result: 8:14:42 PM - GetCommandResults returned 8:14:40 PM - Command number 2
--> starting GetCommandResults(8:14:42 PM - Command number 3)
<-- done with GetCommandResults(8:14:42 PM - Command number 3)
GetTask.Id: 3 result: 8:14:44 PM - GetCommandResults returned 8:14:42 PM - Command number 3
[...]
所以,如果我必须逻辑地写出来:
所以,你可以说我正在寻找一种方法来做到这一点,但如上所述,同步队列:
Dim result as String = Await Task.Factory.StartNew(Function() Dim r as String = FunctionThatReturnsString() 返回r 结束功能)
...除了我似乎无法阻止任务一旦创建就执行......
希望此更新有所帮助!
答案 0 :(得分:0)
没有比提出解决方案更好的方法了。既然没有采取任何行动(对于一个棘手的问题没有任何意义,甚至),我希望主持人会看到另一种方式,因为我问如何做得更好 - 但没有问号!
总结此解决方案的尝试:
调用者通过创建一个唯一的guid(用于以后查找结果)和作为字符串的作业来使用q:
Dim jobId As Guid = Guid.NewGuid Dim myCommand As String =&#34; Command for Job#&#34; &安培;我
调用者创建一个Job()实例,使用上面的参数加载它,并将其提交给q:
Dim j as Job = New Job() j.CallerJobID = jobId j.Command = myCommand j.CallerName =&#34;来电者#&#34; &安培;一世 TheJobQ.JobRequest(j)的
最后,调用者通过在TheJobQ上调用GetJobResultAsync()等待结果,使用作为&#39;索引提交的作业提供的guid,如果你愿意的话,找到结果:
Dim jobResult As String = TheJobQ.GetJobResultAsync(CallerJobID).Result
工作示例就在这里,但它在我的脑海中留下了许多问题,一个重要的问题是,将任务放在队列上是否会更好,la:
Dim t As New Task(AddressOf Me.TakeFromQLoop, ct, TaskCreationOptions.LongRunning)
...add to queue; when time, pull off queue and...
t.Start()
讨论:我无法找到一种方法来保持呼叫者在进入/离开q时附加的任务。这样做可能会少得多。这在OP中暗示过。
幸运的是,我在一个模块中编写了这个测试/用例,以便于复制/粘贴。它在VS2012中工作:
Imports System.Collections.Concurrent
Module Module1
Dim TheJobQ As JobQSingleton
'
Sub Main()
TheJobQ = JobQSingleton.GetInstance ' only 1 class can do work (serially/synchronously)
'
' step 1: create the jobs
'
Dim jobList As New ConcurrentQueue(Of Job) ' each client comes up with their own Guid to later retriece their job's results
Dim jobIdList As New ConcurrentQueue(Of Guid) ' this list holds those Guid, so we can iterate at the end and get the results
For i = 1 To 10
Dim jobId As Guid = Guid.NewGuid
Dim myCommand As String = "Command for Job #" & i
Console.WriteLine("[{0}] CallerJobID: {1} Command: {2}", i, jobId.ToString, myCommand)
jobList.Enqueue(New Job() With {.CallerJobID = jobId, .Command = myCommand, .CallerName = "caller #" & i})
jobIdList.Enqueue(jobId)
Next
'
' step 2: submit requests
'
Threading.Thread.Sleep(1000)
For Each jReq As Job In jobList
If jobList.TryDequeue(jReq) Then
TheJobQ.JobRequest(jReq)
End If
Console.WriteLine("[{2}] {0} added {1} to the Q via .JobRequest", jReq.CallerName, jReq.CallerJobID, jobList.Count)
Next
'
' step 3: get results (using retrieveQ created earlier from copying jobList)
'
For Each clientJobId As Guid In jobIdList '.Reverse ' simulates all our clients' provided Guids
Dim jobResult As String = GetWorkResult(clientJobId)
Console.WriteLine("Result of client jobId: {0} is: ""{1}""", clientJobId, jobResult, jobIdList.Count)
Next
Console.WriteLine("done.")
Console.ReadLine()
End Sub
'
' step 3a:
'
Public Function GetWorkResult(CallerJobID As Guid) As String
Dim r As String = ""
r = TheJobQ.GetJobResultAsync(CallerJobID).Result
Return r
End Function
'
'========================================================================
'
' JobQ()
'
Public Class JobQSingleton
#Region "class vars"
' singleton instance
Shared myInstance As JobQSingleton
' requests
Private Q As New ConcurrentQueue(Of Job)
' results
Private ResultsDictionary As New ConcurrentDictionary(Of Guid, Job)
Private DoQLoop As Boolean
#End Region
#Region "constructor"
Private Sub New()
Me.DoQLoop = True
Me.StartLoop()
End Sub
Public Shared Function GetInstance() As JobQSingleton
If IsNothing(myInstance) Then
myInstance = New JobQSingleton
End If
Return myInstance
End Function
Private Sub StartLoop()
Dim cts As New Threading.CancellationTokenSource
Dim ct As Threading.CancellationToken = cts.Token
' (a) with .Start():
'Dim t As New Task(AddressOf Me.TakeFromQLoop, ct, TaskCreationOptions.LongRunning)
't.Start()
' (b) simple AddressOf:
Dim t As Task = task.Factory.StartNew(AddressOf Me.TakeFromQLoop, ct, TaskCreationOptions.LongRunning)
'
Console.WriteLine("Loop started")
End Sub
#End Region
#Region "(public) submit/retrieve jobs"
'=======================================================
'
' step 2a: add a guid for internal use/deugging
'
Public Sub JobRequest(aJobRequest As Job)
With aJobRequest
.QJobID = Guid.NewGuid ' our internal ID
End With
Me.AddJob(aJobRequest)
End Sub
Public Async Function GetJobResultAsync(ByVal jobId As Guid) As Task(Of String)
Return Await Task.Run(Of String)(Function() GetJobResult(jobId))
End Function
'
' callers call one of the above 2 to either give a job, or get results
'
'=======================================================
Private Function GetJobResult(jobId As Guid) As String
Do Until Me.ResultsDictionary.ContainsKey(jobId)
Threading.Thread.Sleep(250)
Loop
Return Me.ResultsDictionary.Item(jobId).Response
End Function
#End Region
Private Sub AddJob(j As Job)
Q.Enqueue(j)
End Sub
Private Sub TakeFromQLoop()
While (Me.DoQLoop)
Dim j As New Job
If Q.TryPeek(j) = True Then
If Q.TryDequeue(j) = True Then
With j
Console.WriteLine("===> Start job ID {0} from caller {1}", .CallerJobID, .CallerName)
Threading.Thread.Sleep(1000)
j.Response = String.Format("The result of the command {0} is {1}", j.Command, Date.Now.ToLongTimeString)
If Me.ResultsDictionary.TryAdd(j.CallerJobID, j) Then
Console.WriteLine("<=== Stop job ID {0} from caller {1}", .CallerJobID, .CallerName)
Else
Console.WriteLine("...error...")
End If
End With
End If
End If
Threading.Thread.Sleep(1000)
End While
End Sub
End Class
'
' holds the job & results...
'
Public Class Job
Public Property JobName As String
Public Property QJobID As Guid
Public Property CallerName As String
Public Property CallerJobID As Guid
Public Property Command As String
Public Property Response As String
End Class
End Module
输出(不使用上面注释掉的.Reverse选项)
Loop started
[1] CallerJobID: d4a1f479-1d27-4b2f-8d9c-5db1fbacf906 Command: Command for Job #1
[2] CallerJobID: 06a4a886-4054-426b-b963-88e54d4aeda7 Command: Command for Job #2
[3] CallerJobID: 1415bb08-607c-4bf0-9b28-a1f33eb24c33 Command: Command for Job #3
[4] CallerJobID: 18568325-ce4e-4ece-aeff-4f03b20567bf Command: Command for Job #4
[5] CallerJobID: adaffd34-8c76-48eb-a9e3-dbbf3d7cfd1f Command: Command for Job #5
[6] CallerJobID: fabc4ae2-681c-44fa-be83-24c185fc6a54 Command: Command for Job #6
[7] CallerJobID: 7532a8f8-8f97-471a-914b-e1dd9cc88f29 Command: Command for Job #7
[8] CallerJobID: 433338db-94d3-41c1-a003-f883a57059ca Command: Command for Job #8
[9] CallerJobID: b1a47e95-c48c-4b36-b6eb-1c582148d564 Command: Command for Job #9
[10] CallerJobID: 63707629-2140-431b-a91f-13f0b8a37239 Command: Command for Job #10
[9] caller #1 added d4a1f479-1d27-4b2f-8d9c-5db1fbacf906 to the Q via .JobRequest
[8] caller #2 added 06a4a886-4054-426b-b963-88e54d4aeda7 to the Q via .JobRequest
[7] caller #3 added 1415bb08-607c-4bf0-9b28-a1f33eb24c33 to the Q via .JobRequest
[6] caller #4 added 18568325-ce4e-4ece-aeff-4f03b20567bf to the Q via .JobRequest
[5] caller #5 added adaffd34-8c76-48eb-a9e3-dbbf3d7cfd1f to the Q via .JobRequest
[4] caller #6 added fabc4ae2-681c-44fa-be83-24c185fc6a54 to the Q via .JobRequest
[3] caller #7 added 7532a8f8-8f97-471a-914b-e1dd9cc88f29 to the Q via .JobRequest
[2] caller #8 added 433338db-94d3-41c1-a003-f883a57059ca to the Q via .JobRequest
[1] caller #9 added b1a47e95-c48c-4b36-b6eb-1c582148d564 to the Q via .JobRequest
[0] caller #10 added 63707629-2140-431b-a91f-13f0b8a37239 to the Q via .JobRequest
===> Start job ID d4a1f479-1d27-4b2f-8d9c-5db1fbacf906 from caller caller #1
<=== Stop job ID d4a1f479-1d27-4b2f-8d9c-5db1fbacf906 from caller caller #1
Result of client jobId: d4a1f479-1d27-4b2f-8d9c-5db1fbacf906 is: "The result of the command Command for Job #1 is 7:27:41 PM"
===> Start job ID 06a4a886-4054-426b-b963-88e54d4aeda7 from caller caller #2
<=== Stop job ID 06a4a886-4054-426b-b963-88e54d4aeda7 from caller caller #2
Result of client jobId: 06a4a886-4054-426b-b963-88e54d4aeda7 is: "The result of the command Command for Job #2 is 7:27:43 PM"
===> Start job ID 1415bb08-607c-4bf0-9b28-a1f33eb24c33 from caller caller #3
<=== Stop job ID 1415bb08-607c-4bf0-9b28-a1f33eb24c33 from caller caller #3
Result of client jobId: 1415bb08-607c-4bf0-9b28-a1f33eb24c33 is: "The result of the command Command for Job #3 is 7:27:45 PM"
===> Start job ID 18568325-ce4e-4ece-aeff-4f03b20567bf from caller caller #4
<=== Stop job ID 18568325-ce4e-4ece-aeff-4f03b20567bf from caller caller #4
Result of client jobId: 18568325-ce4e-4ece-aeff-4f03b20567bf is: "The result of the command Command for Job #4 is 7:27:47 PM"
===> Start job ID adaffd34-8c76-48eb-a9e3-dbbf3d7cfd1f from caller caller #5
<=== Stop job ID adaffd34-8c76-48eb-a9e3-dbbf3d7cfd1f from caller caller #5
Result of client jobId: adaffd34-8c76-48eb-a9e3-dbbf3d7cfd1f is: "The result of the command Command for Job #5 is 7:27:49 PM"
===> Start job ID fabc4ae2-681c-44fa-be83-24c185fc6a54 from caller caller #6
<=== Stop job ID fabc4ae2-681c-44fa-be83-24c185fc6a54 from caller caller #6
Result of client jobId: fabc4ae2-681c-44fa-be83-24c185fc6a54 is: "The result of the command Command for Job #6 is 7:27:51 PM"
===> Start job ID 7532a8f8-8f97-471a-914b-e1dd9cc88f29 from caller caller #7
<=== Stop job ID 7532a8f8-8f97-471a-914b-e1dd9cc88f29 from caller caller #7
Result of client jobId: 7532a8f8-8f97-471a-914b-e1dd9cc88f29 is: "The result of the command Command for Job #7 is 7:27:53 PM"
===> Start job ID 433338db-94d3-41c1-a003-f883a57059ca from caller caller #8
<=== Stop job ID 433338db-94d3-41c1-a003-f883a57059ca from caller caller #8
Result of client jobId: 433338db-94d3-41c1-a003-f883a57059ca is: "The result of the command Command for Job #8 is 7:27:55 PM"
===> Start job ID b1a47e95-c48c-4b36-b6eb-1c582148d564 from caller caller #9
<=== Stop job ID b1a47e95-c48c-4b36-b6eb-1c582148d564 from caller caller #9
Result of client jobId: b1a47e95-c48c-4b36-b6eb-1c582148d564 is: "The result of the command Command for Job #9 is 7:27:57 PM"
===> Start job ID 63707629-2140-431b-a91f-13f0b8a37239 from caller caller #10
<=== Stop job ID 63707629-2140-431b-a91f-13f0b8a37239 from caller caller #10
Result of client jobId: 63707629-2140-431b-a91f-13f0b8a37239 is: "The result of the command Command for Job #10 is 7:27:59 PM"
done.
...这次 WITH .Reverse取消注释:
Loop started
[1] CallerJobID: 596de3ee-04e2-49dd-aaeb-e4a2aa41c90a Command: Command for Job #1
[2] CallerJobID: cbf0ab0d-5637-4708-837b-3bf7d605f6e1 Command: Command for Job #2
[3] CallerJobID: d8ba30c6-7729-4f91-8d86-51dfbf3b4b3f Command: Command for Job #3
[4] CallerJobID: 292d6212-de33-471a-9fdc-dad8b4bef4d4 Command: Command for Job #4
[5] CallerJobID: 992af5e4-a713-400c-9792-578ac39c6879 Command: Command for Job #5
[6] CallerJobID: f87a09fa-8cba-4d56-9658-567f0ef6d63e Command: Command for Job #6
[7] CallerJobID: fc7a1f0c-1a75-44ce-93bf-dc80d6c810c7 Command: Command for Job #7
[8] CallerJobID: 01d6af2c-5998-4b38-9244-006e9e12f309 Command: Command for Job #8
[9] CallerJobID: cae99dd9-e7e2-4614-be5b-a75d944e27bd Command: Command for Job #9
[10] CallerJobID: 3f02a3bb-5667-48fb-ab22-df8d951b2b13 Command: Command for Job #10
[9] caller #1 added 596de3ee-04e2-49dd-aaeb-e4a2aa41c90a to the Q via .JobRequest
[8] caller #2 added cbf0ab0d-5637-4708-837b-3bf7d605f6e1 to the Q via .JobRequest
[7] caller #3 added d8ba30c6-7729-4f91-8d86-51dfbf3b4b3f to the Q via .JobRequest
[6] caller #4 added 292d6212-de33-471a-9fdc-dad8b4bef4d4 to the Q via .JobRequest
[5] caller #5 added 992af5e4-a713-400c-9792-578ac39c6879 to the Q via .JobRequest
[4] caller #6 added f87a09fa-8cba-4d56-9658-567f0ef6d63e to the Q via .JobRequest
[3] caller #7 added fc7a1f0c-1a75-44ce-93bf-dc80d6c810c7 to the Q via .JobRequest
[2] caller #8 added 01d6af2c-5998-4b38-9244-006e9e12f309 to the Q via .JobRequest
[1] caller #9 added cae99dd9-e7e2-4614-be5b-a75d944e27bd to the Q via .JobRequest
[0] caller #10 added 3f02a3bb-5667-48fb-ab22-df8d951b2b13 to the Q via .JobRequest
===> Start job ID 596de3ee-04e2-49dd-aaeb-e4a2aa41c90a from caller caller #1
<=== Stop job ID 596de3ee-04e2-49dd-aaeb-e4a2aa41c90a from caller caller #1
===> Start job ID cbf0ab0d-5637-4708-837b-3bf7d605f6e1 from caller caller #2
<=== Stop job ID cbf0ab0d-5637-4708-837b-3bf7d605f6e1 from caller caller #2
===> Start job ID d8ba30c6-7729-4f91-8d86-51dfbf3b4b3f from caller caller #3
<=== Stop job ID d8ba30c6-7729-4f91-8d86-51dfbf3b4b3f from caller caller #3
===> Start job ID 292d6212-de33-471a-9fdc-dad8b4bef4d4 from caller caller #4
<=== Stop job ID 292d6212-de33-471a-9fdc-dad8b4bef4d4 from caller caller #4
===> Start job ID 992af5e4-a713-400c-9792-578ac39c6879 from caller caller #5
<=== Stop job ID 992af5e4-a713-400c-9792-578ac39c6879 from caller caller #5
===> Start job ID f87a09fa-8cba-4d56-9658-567f0ef6d63e from caller caller #6
<=== Stop job ID f87a09fa-8cba-4d56-9658-567f0ef6d63e from caller caller #6
===> Start job ID fc7a1f0c-1a75-44ce-93bf-dc80d6c810c7 from caller caller #7
<=== Stop job ID fc7a1f0c-1a75-44ce-93bf-dc80d6c810c7 from caller caller #7
===> Start job ID 01d6af2c-5998-4b38-9244-006e9e12f309 from caller caller #8
<=== Stop job ID 01d6af2c-5998-4b38-9244-006e9e12f309 from caller caller #8
===> Start job ID cae99dd9-e7e2-4614-be5b-a75d944e27bd from caller caller #9
<=== Stop job ID cae99dd9-e7e2-4614-be5b-a75d944e27bd from caller caller #9
===> Start job ID 3f02a3bb-5667-48fb-ab22-df8d951b2b13 from caller caller #10
<=== Stop job ID 3f02a3bb-5667-48fb-ab22-df8d951b2b13 from caller caller #10
Result of client jobId: 3f02a3bb-5667-48fb-ab22-df8d951b2b13 is: "The result of the command Command for Job #10 is 7:30:12 PM"
Result of client jobId: cae99dd9-e7e2-4614-be5b-a75d944e27bd is: "The result of the command Command for Job #9 is 7:30:10 PM"
Result of client jobId: 01d6af2c-5998-4b38-9244-006e9e12f309 is: "The result of the command Command for Job #8 is 7:30:08 PM"
Result of client jobId: fc7a1f0c-1a75-44ce-93bf-dc80d6c810c7 is: "The result of the command Command for Job #7 is 7:30:06 PM"
Result of client jobId: f87a09fa-8cba-4d56-9658-567f0ef6d63e is: "The result of the command Command for Job #6 is 7:30:04 PM"
Result of client jobId: 992af5e4-a713-400c-9792-578ac39c6879 is: "The result of the command Command for Job #5 is 7:30:02 PM"
Result of client jobId: 292d6212-de33-471a-9fdc-dad8b4bef4d4 is: "The result of the command Command for Job #4 is 7:30:00 PM"
Result of client jobId: d8ba30c6-7729-4f91-8d86-51dfbf3b4b3f is: "The result of the command Command for Job #3 is 7:29:58 PM"
Result of client jobId: cbf0ab0d-5637-4708-837b-3bf7d605f6e1 is: "The result of the command Command for Job #2 is 7:29:56 PM"
Result of client jobId: 596de3ee-04e2-49dd-aaeb-e4a2aa41c90a is: "The result of the command Command for Job #1 is 7:29:54 PM"
done.
P.S。是的,我确实使用了“工作”这些术语。和&#39;工作&#39;并且&#39;要求&#39;同义词......这是一个科学怪人...... P.S.S.我没有包括删除包含解决方案的词典条目,一旦它们被选中,并且......直到我收到同行反馈,我才能整理一下...
我不允许以问号结束解决方案帖子,所以你必须想象它在那里......