我正在为Azure Table Storage做一堆或asynchronous calls
。由于显而易见的原因,这些记录的插入顺序与它们被调用的顺序不同。
我计划引入ConcurrentQueue
以确保顺序。以下作为POC编写的示例代码似乎达到了预期的结果。
我想知道这是我可以确保异步调用的最佳方式 将按顺序完成?
public class ProductService
{
ConcurrentQueue<string> ordersQueue = new ConcurrentQueue<string>();
//Place make calls here
public void PlaceOrder()
{
Task.Run(() =>
{
Parallel.For(0, 100, (i) =>
{
string item = "Product " + i;
ordersQueue.Enqueue(item);
Console.WriteLine("Placed Order: " + item);
Task.Delay(2000).Wait();
});
});
}
//Process calls in sequence, I am hoping concurrentQueue will be consistent.
public void Deliver()
{
Task.Run(() =>
{
while(true)
{
string productId;
ordersQueue.TryDequeue(out productId);
if (!string.IsNullOrEmpty(productId))
{
Console.WriteLine("Delivered: " + productId);
}
}
});
}
}
答案 0 :(得分:4)
如果你想以异步和顺序的方式处理记录,这听起来非常适合TPL Dataflow的ActionBlock
。只需创建一个包含要执行的操作的块,并将记录发布到该块。它支持async
个动作并保持秩序:
var block = new ActionBlock<Product>(async product =>
{
await product.ExecuteAsync();
});
block.Post(new Product());
如果需要,它还支持并行处理和有限容量处理。
答案 1 :(得分:1)
尝试使用Microsoft的Reactive Framework。
这对我有用:
IObservable<Task<string>> query =
from i in Observable.Range(0, 100, Scheduler.Default)
let item = "Product " + i
select AzureAsyncCall(item);
query
.Subscribe(async x =>
{
var result = await x;
/* do something with result */
});
我使用的AzureAsyncCall
来电签名是public Task<string> AzureAsyncCall(string x)
。
我放弃了一堆Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
次调用,以确保我在测试代码中获得了正确的异步行为。它运作良好。
所有调用都是异步的,并且一个接一个地序列化。