我正在尝试使用异步和任务从存储中加载和处理数据。
我通常使用带有连接的两个线程来执行此任务,但是我想尝试这种语言功能。
代码很简单
Foreach(var file in files)
{
var data = LoadFromFile(file); // require 3sec
ProcessData(data); // require 5 sec
}
我将在加载下一个数据时处理数据。
谢谢
答案 0 :(得分:1)
您可以结合生产者-消费者集合和处理任务来执行此操作。生产者-消费者模式的总体思想是,您有一个数据生产者和一个或多个数据消费者,而且它们具有不同的运行速度。
在您的情况下,数据每3秒钟产生一次,每5秒钟消耗一次,因此您只需要一个处理/消耗任务-生产可以由另一个任务完成,也可以只留给您的主线程-并且像队列一样收集既可以传达工作量又可以等待工作的资源,则不应使用CPU资源。
为此,您可以使用BlockingCollection,其详细信息在https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/blockingcollection-overview中进行了描述。
针对您的案例的示例实现为:
var work = new BlockingCollection<Data>();
// instantiate processing task
var processingTask = Task.Run(() =>
{
foreach (var data in work.GetConsumingEnumerable())
{
ProcessData(data);
}
});
// produce data for processing
for (int i = 0; i < 10; i++)
{
var data = LoadFromFile(file);
work.Add(data); // processing will start as soon as data is added
}
// mark that no more data will come, so the processing knows it doesn't need to wait for more work
work.CompleteAdding();
// await end of processing
await processingTask;
答案 1 :(得分:0)
如果不想在调用ProcessData时阻塞,则需要将其签名更改为:
async Task ProcessData(byte[] data);
然后,您可以像这样不阻塞地调用ProcessData:
await ProcessData(fileContent);
请注意,为了使用await关键字,调用函数本身应该是异步的。此外,您还可以阅读有关异步和等待功能here的很多文章。
答案 2 :(得分:0)
您要寻找的应该是这样的
static void Main()
{
List<string> files = new List<string>() { "file1", "file2" };
foreach (var file in files)
{
Work(file);
}
Console.ReadLine();
}
private static async void Work(string file)
{
var data = await LoadFromFile(file);
await ProcessData(data);
}
private static async Task ProcessData(string data)
{
await Task.Delay(5000);
Console.WriteLine($"Processed {data}");
}
private static async Task<string> LoadFromFile(string file)
{
await Task.Delay(3000);
Console.WriteLine($"Loaded {file}");
return file.Replace("file", "data");
}
但是,我相信您真正需要的是Parallel.ForEach
static void Main()
{
List<string> files = new List<string>() { "file1", "file2" };
Parallel.ForEach(files, (file) =>
{
var data = LoadFromFile(file);
ProcessData(data);
});
Console.ReadLine();
}
private static void ProcessData(string data)
{
Thread.Sleep(3000);
Console.WriteLine($"Processed {data}");
}
private static string LoadFromFile(string file)
{
Thread.Sleep(5000);
Console.WriteLine($"Loaded {file}");
return file.Replace("file", "data");
}
答案 3 :(得分:-1)
您可以像这样使用Parallel.Foreach方法:
foreach(var file in files)
{
var data = LoadFromFile(file);
new TaskFactory().StartNew(() => { ProcessData(data); });
}