Evgeni Velikov
Evgeni Velikov

Reputation: 382

Asynchronous running one method in one time

I have method how need running around 68 times, and this is waiting around 1.2 seconds. Can I running this method in few threads for not wait too much. I try this code but is still too slow. This is my part of code

for (byte parameter = 1; parameter < 5; parameter++)
{
    for (byte step = 0; step < xValues.Count; step++)
    {
        await AddMeasure(av, average, parameter, step, time, file);
    }
}

CreateDiagram(canGraph, points, xValues, yValues);

And this is my async method

private async Task AddMeasure(AverageValue av, Dictionary<DateTime, double> average, byte parameter, byte step, DateTime time, string file)
{
    await Task.Run(() =>
    {
        av.Step = step;
        av.KindOfInfo = parameter;
        average = av.GetInformationForDiagramBetweenTwoTimes(time, file);

        Measure measure = new Measure();
        measure.Average = average.FirstOrDefault().Value;
        measure.Time = average.FirstOrDefault().Key;
        measure.Parameter = parameter;

        this.TimeValueParameter.Add(measure);
    });
}

I would be very greatful if you give me the link for tutorial, or examples with asynchronous programming. I'm new in asynchronous programming and try now to learn for them.

Upvotes: 0

Views: 137

Answers (2)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149518

I'm new in asynchronous programming

There is nothing asynchronous about your code. You want to parallalize it by running CPU bound work on multiple threads.

I would refactor this code and use PLINQ to achieve what you want.

First, I would refactor AddMeasure to be synchronous, because all it's doing is using the async over sync anti-pattern. I would make it return a Measure, because you can't add to a List<T> in parallel from multiple threads, it isn't thread-safe.

private Measure CalculateMeasure(AverageValue av, Dictionary<DateTime, double> average,
                                 byte parameter, byte step, DateTime time, string file)
{
    av.Step = step;
    av.KindOfInfo = parameter;
    average = av.GetInformationForDiagramBetweenTwoTimes(time, file);

    var first = average.First();

    return new Measure
    {
        Average = first.Value;
        Time = first.Key;
        Parameter = parameter;
    };
}

And then invoke it like this:

List<Measure> measures = Enumerable.Range(0, 6)
                                   .Cast<byte>()
                                   .AsParallel()
                                   .SelectMany(parameter => 
{
    var localMeasures = new List<Measure>();
    for (byte step = 0; step < xValues.Count; step++)
    {
        localMeasure.Add(CalculateMeasure(av, average, parameter, step, time, file));
    }
    return localMeasures;
}).ToList();

this.TimeValueParameter.AddRange(measures);

Note that when going parallel, you should measure your code and see if you it actually improves the performance of your code. Don't take it for granted, as it looks like CalculateMeasure isn't doing too much work.

Upvotes: 3

Sandip Bantawa
Sandip Bantawa

Reputation: 2880

Task[] task = new Task[count];
for (byte parameter = 1; parameter < 5; parameter++)
{
    for (byte step = 0; step < xValues.Count; step++)
    {
        task[index] = AddMeasure(av, average, parameter, step, time, file);
    }
}
await Task.WhenAll(task);

await blocks however is asynchronous, so just add continuation of tasks and await all of them below.

Upvotes: 0

Related Questions