Reputation: 130
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:
poi_data
)pois
)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 parameterT
in the generic type or methodSystem.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);
}
Upvotes: 0
Views: 2032
Reputation: 70671
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).
Upvotes: 1