简体   繁体   中英

Parallel.ForEach with Dictionary and multiple local variables in C#

I'm trying to convert a normal function to a parallel function.

The function checks if the coordinates given are close enough to consider them duplicated, checking one by one in a full list of coordinates.

I need access to 3 local variables:

  • Coordinates to be tested ( poi_data )
  • the list of coordinates ( pois )
  • an application variable indicating the distance to be considered duplicate ( Config.duplicatedRange )

Once it is detected a duplicate the function should stop checking and return true .

Here is my current code working.

class Test
{           
    public static Boolean CheckDuplicated (POIData poi_data, 
                Dictionary<string, POIData> pois)
    {
        foreach (KeyValuePair<string, POIData> item in pois)
        {
            Double distance = CalculateDistance (poi_data.latitude,
                        poi_data.longitude,
                        item.Value.latitude,
                        item.Value.longitude);

            if (distance < Config.duplicatedRange) {
                return true;
            }
        }
        return false;
    }
}

public class POIData
{
    public Double longitude { set; get; }

    public Double latitude { set; get; }
}

Here is my attempt to do it in parallel.

public static Boolean CheckDuplicated (POIData poi_data,
        Dictionary<string, POIData> pois)
{
    Boolean result = false;
    CancellationTokenSource cts = new CancellationTokenSource (); 
    ParallelOptions options = new ParallelOptions 
                { CancellationToken = cts.Token }; 

    Parallel.ForEach (pois,
            options,
            () => false,
            (item, loopState, localCount) => {
                cts.Token.ThrowIfCancellationRequested ();
                Double distance = CalculateDistance (poi_data.latitude,
                        poi_data.longitude,
                        item.Value.latitude,
                        item.Value.longitude);
                if (distance < Config.duplicatedRange) {
                    cts.Cancel ();
                    return true;
                }
                return false;
            },
            (tempResult) => {
            if (tempResult == true) {
                Interlocked.Exchange (ref result, tempResult);
            }
        });

    return result;
}

I get an error

Error CS0452: The type bool must be a reference type in order to use it as type parameter T in the generic type or method System.Threading.Interlocked.Exchange<T>(ref T, T)

What am I doing wrong? is this the best way to do this or is there an easier way?

EDIT:

Thank you for your help, here the updated and working function :)

public static Boolean CheckDuplicated (POIData poi_data, 
                                       Dictionary<string, POIData> pois)
{
    int result = 0;
    Parallel.ForEach (pois,
        () => 0,
        (item, loopState, tempResult) => {
            Double distance = CalculateDistance (poi_data.latitude,
                                  poi_data.longitude,
                                  item.Value.latitude,
                                  item.Value.longitude);

            if (distance < Config.duplicatedRange) {
                loopState.Stop ();
                return 1;
            }
            return 0;
        },
        (tempResult) => {
            if (tempResult == 1) {
                Interlocked.Exchange (ref result, tempResult);
            }
        });
    return Convert.ToBoolean (result);
}

Basically: there is no overload of the Interlocked.Exchange() method that will accept bool as a parameter type. None of the explicitly typed method overloads include bool , so the compiler tries to match the generic method overload, but that then fails because of the generic constraint of the type parameter.

The easiest alternative is to simply not use bool as the type for your result variable. Make it an int instead, initialize it to 0 , and set it to 1 if you find the item you're looking for.


(I didn't look closely at the overall implementation in your code. At first glance it seems fine, and your question appears to be specifically about the error message, so I only address that above).

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