I'm trying to use async and task to load and process data from storage.
I usually do this task with two threads with join but i want try this language functionality.
The code is very simple
Foreach(var file in files)
{
var data = LoadFromFile(file); // require 3sec
ProcessData(data); // require 5 sec
}
I would process the data while it's loading the next data.
Thanks
You can do this with a producer-consumer collection in conjunction with a processing task. The general idea of the producer-consumer pattern that you have a data producer and one or more data consumers, which additionally have different operation speeds.
In your case data is produced every 3s and consumed every 5s, so you just need a processing/consumption task - the production may be done by another task or can be just left to your main thread - and queue-like collection over which both communicate their workload and waiting for work should not use CPU resources.
For this you can use a BlockingCollection, whose details are described at https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/blockingcollection-overview .
An example implementation for your case would be:
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;
If you want don't want to block when calling ProcessData, you need to change it's signature to something like:
async Task ProcessData(byte[] data);
Then, you can call ProcessData without blocking, like that:
await ProcessData(fileContent);
Be aware that in order to use the await keyword, the calling function should be async itself. Also, You can read a lot about async & await feature here .
What you are looking for should be something like this
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");
}
However, I believe what you really need is 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");
}
You can use Parallel.Foreach method like this :
foreach(var file in files)
{
var data = LoadFromFile(file);
new TaskFactory().StartNew(() => { ProcessData(data); });
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.