背景我们有一个服务操作,可以接收并发的异步请求,并且必须一次处理一个请求。在下面的示例中,该UploadAndImport(...)方法在多个线程上接收并发请求,但是对该ImportFile(...)方法的调用必须一次进行一次。外行人说明想象一下一个有很多工人(多线程)的仓库。人员(客户)可以同时(同时)向仓库发送许多包裹(请求)。当包裹进来时,工人要自始至终负责,丢下包裹的人可以离开(开火忘了)。工人的工作是将每个包裹放进一个小斜槽,一次只能有一个工人将一个包裹放进一个斜槽,否则会造成混乱。如果放下包裹的人员稍后再进站(轮询端点),则仓库应能够报告包裹是否从斜槽滑落。问题然后的问题是如何编写一个服务操作...可以接收并发客户端请求,在多个线程上接收并处理这些请求,在收到请求的同一线程上处理请求,一次处理一个请求,是一种“一劳永逸”的操作,并且有一个单独的轮询端点,该端点报告请求完成情况。我们已经尝试了以下方法,并且想知道两件事:有没有我们没有考虑过的竞争条件?有没有一种更规范的方法可以在C#.NET中使用面向服务的体系结构(我们恰好使用WCF)对这种情况进行编码?示例:我们尝试过什么?这是我们尝试过的服务代码。它的工作原理虽然听起来有些像是乱砍或l头。static ImportFileInfo _inProgressRequest = null;static readonly ConcurrentDictionary<Guid, ImportFileInfo> WaitingRequests = new ConcurrentDictionary<Guid, ImportFileInfo>();public void UploadAndImport(ImportFileInfo request){ // Receive the incoming request WaitingRequests.TryAdd(request.OperationId, request); while (null != Interlocked.CompareExchange(ref _inProgressRequest, request, null)) { // Wait for any previous processing to complete Thread.Sleep(500); } // Process the incoming request ImportFile(request); Interlocked.Exchange(ref _inProgressRequest, null); WaitingRequests.TryRemove(request.OperationId, out _);}public bool UploadAndImportIsComplete(Guid operationId) => !WaitingRequests.ContainsKey(operationId);这是示例客户端代码。private static async Task UploadFile(FileInfo fileInfo, ImportFileInfo importFileInfo){ using (var proxy = new Proxy()) using (var stream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read)) { importFileInfo.FileByteStream = stream; proxy.UploadAndImport(importFileInfo); } await Task.Run(() => Poller.Poll(timeoutSeconds: 90, intervalSeconds: 1, func: () => { using (var proxy = new Proxy()) { return proxy.UploadAndImportIsComplete(importFileInfo.OperationId); } }));}很难在Fiddle中编写一个最小的可行示例,但这是一个有意义并可以编译的开始。和以前一样,以上内容似乎很容易破解,我们既在询问其方法可能存在的陷阱,又在询问更合适/规范的替代模式。
3 回答
- 3 回答
- 0 关注
- 143 浏览
添加回答
举报
0/150
提交
取消