简体   繁体   中英

Example Async Task c#

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM