Why is Parallel.ForEach loop only doing a shallow copy? - c#

I have the following code:
List<List<Material>> materialCombos;
Parallel.ForEach(materialCombos, combination =>
{
Material material1 = combination[0];
Material material2 = combination[1];
double[] tempValues1 =
material1.MaterialImages
.OrderBy(mi => mi.Time)
.Select(mi => Convert.ToDouble(mi.Temperature))
.ToArray();
});
public class Material
{
[Key]
public int MaterialID { get; set; }
/// <summary>
/// Name of the material.
/// </summary>
public string Name { get; set; }
// other accessors here...
/// <summary>
/// Collection of apparent temperature images with meta-data for this material.
/// </summary>
public virtual ICollection<MaterialImage> MaterialImages { get; set; }
}
It works perfectly fine when using the synchronous foreach loop. However, when I use the parallel version (as above), the MaterialImages object doesn't always copy across to the combination object and when viewing it in the debugger it is null and therefore an exception is thrown in the anonymous function.
Any ideas why this is happening, is it because when it iterates through materialCombos and gets each combination out it does a shallow copy?

Your original post left out the fact that you're using objects from the EF object context. Since that's not thread-safe, you can't do what you want in parallel. It may work to retrieve all the objects and then operate on them concurrently, but I'm not an expert in EF.

You should probably be using a thread safe collection. Switch your type to a ConcurrentBag<ConcurrentBag<Material>> for starters. Also, doesnt look like you are showing what you are doing with the array within the loop (the snippet of code is incomplete)....if you are expecting to access anything you build up within the loop outside of the parralel loop, you will need to make sure that it is also using a thread safe implementation.
What you are probably seeing in the debugger is non-deterministic behaviour due to the threading.

Related

How to Access Parameters of User Variables in SSIS Script Task

I have a variable [User::WorkOrderProductIdList] in SSIS package containing records of a class object.
Work Order Product class
public class WorkOrderProduct
{
public Guid workOrderId;
public Guid workOrderProductId;
public static Guid WorkOrderId { get; set; }
public static Guid WorkOrderProductId { get; set; }
}
Main Script Task
public override void InputWOProduct_ProcessInputRow(InputWOProductBuffer Row)
{
ArrayList wopList = new ArrayList();
WorkOrderProduct wop = new WorkOrderProduct();
wop.workOrderId = pWorkOrderID;
wop.workOrderProductId = pWorkOrderProductID;
wopList.Add(wop);
}
Assign wopList to [User::WorkOrderProductIdList]
public override void PostExecute()
{
base.PostExecute();
Variables.WorkOrderProductIdList = this.wopList;
}
In another script task, it takes in [User::WorkOrderProductIdList] as ReadOnlyVariables.
May I know how can I loop through [User::WorkOrderProductIdList] and extract the values of workOrderId and workOrderProductId for each row?
I saw that my ArrayList [User::WorkOrderProductIdList] contains the records and values, but there are no functions when . on the field.
Population
Intellisense issue aside, you'll only ever have at most 1 row in there
You are using a Data Flow and within that, you have a Script Component acting as a Transformation.
In InputWOProduct_ProcessInputRow which fires for each row that passes through the component, you have
Every time a new row comes in, you are going to empty out the existing ArrayList and reinitialize it.
Instead, you need to have that variable at the class scope and have the initialization logic in the not-shown PreExecute method
ArrayList wopList;
// Or, if you wish to use the Generics
// List<WorkOrderProduct> wopList
public override void PreExecute()
{
base.PreExecute();
/*
* Add your code here
*/
this.wopList = new ArrayList();
// Or
// this.wopList = new List<WorkOrderProduct>();
}
Consumption
You use the ArrayList to hold the elements of your array but that is a weakly typed list.
We don't recommend that you use the ArrayList class for new development. Instead, we recommend that you use the generic List class.
When you're enumerating through it in your foreach loop, what is getting popped off the list is of type Object. Not only do I just "know" that, itellisense is telling you that all it knows is the type is Object because it's giving you the functions that everything has because they're all derived from Object.
Yes, the Watch window has inspection magic to show you what the values are but do you think the team that wrote the former is the same team that wrote the latter?
Since you "know" what the type should be, declare it as such.
foreach (WorkOrderProduct wopObj in ...
However, the next logical error, probably, is going to be in the accessing of
Variables.WorkOrderProductIdList itself. Your snipped image there shows you're shredding out the array in the PreExecute method. The sequence of operations is that the Data Flow is going to go through validation, then pre-execute sequences so at that point, it's going to shred the results of your array list and the value of wopObj_workOrderId is going to be the last element of your array.

How to create a generic class that can take many parameters

Okay, so I am creating a Utility AI framework. For this to work I need a class that can change a lot depending on the situation I am sure, and I hope that there is a way to use polymorphism or some sort of design pattern to solve my issue.
Let me show you what I mean
I have an action for the sake of example let's say I have the following action Attack Target
This action can have a number of considerations that will vary a lot but all implement the same interface:
public interface IConsideration
{
/// <summary>
/// A unique named identifier for this consideration.
/// </summary>
string NameId { get; }
/// <summary>
/// The weight of this consideration.
/// </summary>
float Weight { get; set; }
/// <summary>
/// If true, then the output of the associated evaluator is inverted, in effect, inverting the
/// consideration.
/// </summary>
bool IsInverted { get; set; }
/// <summary>Calculates the utility given the specified context.</summary>
/// <param name="context">The context.</param>
/// <param name="value"></param>
/// <returns>The utility.</returns>
float Consider<T>(BaseAiContext context, T value);
}
The above is my current implementation it doesn't really solve the issue I have
As you can see the "most" important method of this interface is the Consider
and here lies the issue preferably I should be able to pass data to this class in a way that I can control.
For the sake of example let's say one consideration I have is Move To Location here I want to send the following parameters:
Location of target
Weapon type (ranged / melee)
location list
The above is just an example to prove my point. There is another issue with this - how can I pass the correct parameters when I finally have them? say that I have the following code:
public List<IConsideration> considerations;
float targetDistance = 2;
for (int i = 0; i < considerations.Count; i++)
{
float AxisScore = considerations[i].Consider(BaseAiContext,targetDistance );
}
Since I have to use the Interface type I am unable to know exactly which values to parse as parameters.
To sum it up:
How can i "parameterize" my class in a generic way?
How can I distinguish these parameterizations so I can provide a consideration with the correct values?
As #MarcRasmussen requested an example
As each implementation of your interface might consume different sets of arguments one way to solve it would be to kind of have key-value storage like a dictionary.
There are plenty of improvements to be made like, using ENUMS instead of strings, and having a static manager class for things like that to add/modify/remove settings.
This is a quick example and not tested, with the information available.
public class MoveToTarget : IConsideration
{
//method is changed to have generic return type and accept dictionary for settings
float Consider(BaseAiContext context, Dictionary<string,object> settings){
//make sure required keys exist
if(!settings.ContainsKey("DESTINATION"))
throw new ApplicationException("Missing key DESTINATION");
if(!settings.ContainsKey("SPEED"))
throw new ApplicationException("Missing key SPEED");
// retrieve you required settings, at this stage since you cast an object, you should check the type ... this problem would be solved if you have (as further below mentioned) a specific settings class for all your implementations. this way you ensure type safety too.
Point destination = (Point)settings["DESTINATION"];
float speed = (float)settings["SPEED"];
// and perform whatever logic you need. etc.
}
}
public List<IConsideration> considerations;
//this should be probably static and globally available (?) probably better to have a singleton manager class to deal with that.
Dictionary<string,object> Settings = new Dictionary<string,object>()
{
{"SPEED", 1.0f},
{"RANDOM", new Random()},
{"DESTINATION", new Point()},
{"XYZ", "XYZ"},
//etc.
}
//use foreach unless you need to have access to the index
foreach(var consideration in considerations)
{
float AxisScore = consideration.Consider(BaseAiContext, Settings);
}
some other improvements could be to have a specific settings class for each of your implementations like MoveToTargetSettings and then instead of havin ambiguous "KEYS" in a dictionary you can retrieve the specific settings by its class etc. like var settings = settingDictionary["MoveToTargetSettins"] as MoveToTargetSettings
I think for anything better more details are required, happy to discuss and answer any further questions outside of SO as that will be off-topic :)

How to limit a string to a set of dynamically-defined values?

I have a class that has a string property for which I'd like to limit the possible values to a set defined dynamically (e.g. stored in the database, though we're using code-first EF6). Using an Enum is obviously out. I did some reading about Code Contracts and like the look of that, but don't know the first thing about establishing a Contract.Requires that pulls back a set of values. Lambda, maybe? I'm on the bleeding edge of my understanding here.
Here's some sample code:
public class Rule
{
/// <summary>The Conditions associated with this Rule
/// </summary>
public ICollection<Condition> Conditions { get; set; }
// ... some other stuff ...
/// <summary>The Status of the Rule.
/// </summary>
public string RuleStatus
{
get{}
set
{
// Here's where I want to dynamically determine values
Contract.Requires(value == "Inactive"||"Obsolete");
// Perhaps something like this,
// where GetValidRuleStatuses returns an array of string??
Contract.Requires(GetValidRuleStatuses().Contains(value));
}
}
One way to do this, is to write custom code to actually perform the check as and when you need to.
In terms of data structures, I'd recommend a HashSet<string> for fast lookups, which you will need to populate:
//Cache this somewhere, until the values change
var allowedValues = new HashSet<string>(stringValues);
if(!allowedValues.Contains(attemptedValue))
{
//Throw exception?
}

Thread-safe enumeration of shared memory that can be updated or deleted

I have a shared object between threads that is used to hold file state information. The object that holds the information is this class:
/// <summary>
/// A synchronized dictionary class.
/// Uses ReaderWriterLockSlim to handle locking. The dictionary does not allow recursion by enumeration. It is purly used for quick read access.
/// </summary>
/// <typeparam name="T">Type that is going to be kept.</typeparam>
public sealed class SynchronizedDictionary<U,T> : IEnumerable<T>
{
private System.Threading.ReaderWriterLockSlim _lock = new System.Threading.ReaderWriterLockSlim();
private Dictionary<U, T> _collection = null;
public SynchronizedDictionary()
{
_collection = new Dictionary<U, T>();
}
/// <summary>
/// if getting:
/// Enters read lock.
/// Tries to get the value.
///
/// if setting:
/// Enters write lock.
/// Tries to set value.
/// </summary>
/// <param name="key">The key to fetch the value with.</param>
/// <returns>Object of T</returns>
public T this[U key]
{
get
{
_lock.EnterReadLock();
try
{
return _collection[key];
}
finally
{
_lock.ExitReadLock();
}
}
set
{
Add(key, value);
}
}
/// <summary>
/// Enters write lock.
/// Removes key from collection
/// </summary>
/// <param name="key">Key to remove.</param>
public void Remove(U key)
{
_lock.EnterWriteLock();
try
{
_collection.Remove(key);
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// Enters write lock.
/// Adds value to the collection if key does not exists.
/// </summary>
/// <param name="key">Key to add.</param>
/// <param name="value">Value to add.</param>
private void Add(U key, T value)
{
_lock.EnterWriteLock();
if (!_collection.ContainsKey(key))
{
try
{
_collection[key] = value;
}
finally
{
_lock.ExitWriteLock();
}
}
}
/// <summary>
/// Collection does not support iteration.
/// </summary>
/// <returns>Throw NotSupportedException</returns>
public IEnumerator<T> GetEnumerator()
{
throw new NotSupportedException();
}
/// <summary>
/// Collection does not support iteration.
/// </summary>
/// <returns>Throw NotSupportedException</returns>
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotSupportedException();
}
}
I call this dictionary like this:
SynchronizedDictionary _cache = new SynchronizedDictionary();
Other threads can be spawned and use the thread like this:
_cache["key"];
The dictionary can be modified at runtime. I see no problem here. Or am I wrong?
The problem, in my eyes, lies in the enumerator, because I want to make an enumerator that iterates over the collection. How do I do this? I have thought of these three solutions:
Making a Enumerator like this:
http://www.codeproject.com/Articles/56575/Thread-safe-enumeration-in-C
(but using ReaderWriterLockSlim)
Expose the lock object, like SyncRoot does (but with
ReaderWriterLockSlim), so a caller calls the enter and exit read methods.
Use a database (SQLite fx) instead, holding the information.
The problem with number 1) is:
it uses the contructor to entry read mode. What if the
GetEnumerator() is call manually, not using the foreach? And forget
calling dispose.
I do not know if this is a good coding style. Even though I like the
code.
If the caller uses a foreach, I do not know what the caller might do
between the instantiation of the enumerator and the call to dispose.
If I have understood the documentation I have read correct this can
end up blocking the writer as long as there is one reader left doing
some heavy work.
The problem with number 2) is:
I do not like exposing this. I know that the .NET API does it, but
do not like it.
It is up to the caller to enter and exit properly
There is no problem with 3) I my eyes. But I am doing this small project as a spare time project and I want to learn more about multi-threading and reflection, so I want to keep this as a last option.
The reason why I want to iterate over the collection at runtime is that I want to find the values, that matches some criteria.
Maybe it is just me that have invented a problem?
I know of ConcurrentDictionary, but I do not want to use this. I am using this project as a playground. Playing with threading and reflection.
EDIT
I have been asked what it is that I am reading and writing. And I am going to tell this in this edit. I am reading and writing this class:
public class AssemblyInformation
{
public string FilePath { get; private set; }
public string Name { get; private set; }
public AssemblyInformation(string filePath, string name)
{
FilePath = filePath;
Name = name;
}
}
I am doing alot of reads, and almost no writes at runtime. Maybe I will do 2000 and 1 write. There is not going to be alot of object either, maybe 200.
I'll treat your questions as a request for feedback which helps you learn. Let me address the three solutions you have already identified:
Yes, this is why such a design should never be exposed as an API to a 3rd-party (or even other developers). It is tricky to use correctly. This codeproject article has some nasty advice.
Much better because this model would be explicit about locking, not implicit. However this violates separation of concerns in my opinion.
Not sure what you mean here. You could have a Snapshot() method on your dictionary which does a read-only copy which can be safely passed around and read. This is a different trade-off than solution 1.
There is a different solution entirely: Use an immutable dictionary. Such a dictionary could be passed around, read and enumerated safely even under concurrent write access. Such dictionaries/maps are commonly implemented using trees.
I'll elaborate more on a key point: You need to think about the concurrent system as a whole. You cannot make you app correct by making all components thread-safe (in your case a dictionary). You need to define, what you are using the dictionary for.
You say:
The reason why I want to iterate over the collection at runtime is
that I want to find the values, that matches some criteria.
You you have concurrent writes happening to the data and want to get a consistent snapshot atomically from the dictionary (maybe to shot some progress report in the UI?). Now that we know this goal, we can devise a solution:
You could add a Clone method to your dictionary which clones all data while taking the read-lock. This will give the caller a fresh object which it can then enumerate over independently. This would be a clean and safely exposable API.
Instead of implementing IEnumerable directly I would add a Values property (like Dictionary.Values):
public IEnumerable<T> Values {
get {
_lock.EnterReadLock();
try {
foreach (T v in _collection.Values) {
yield return v;
}
} finally {
_lock.ExitReadLock();
}
}
}

Obsolete attribute causes property to be ignored by XmlSerialization

I'm refactoring some objects that are serialized to XML but need to keep a few properties for backwards compatibility, I've got a method that converts the old object into the new one for me and nulls the obsolete property. I want to use the Obsolete attribute to tell other developers not to use this property but it is causing the property to be ignored by the XmlSerializer.
Similar Code:
[Serializable]
public class MySerializableObject
{
private MyObject _oldObject;
private MyObject _anotherOldObject;
private MyObject _newBetterObject;
[Obsolete("Use new properties in NewBetterObject to prevent duplication")]
public MyObject OldObject
{
get { return _oldObject; }
set { _oldObject = value; }
}
[Obsolete("Use new properties in NewBetterObject to prevent duplication")]
public MyObject AnotherOldObject
{
get { return _anotherOldObject; }
set { _anotherOldObject = value; }
}
public MyObject NewBetterObject
{
get { return _anotherOldObject; }
set { _anotherOldObject = value; }
}
}
Any ideas on a workaround? My best solution is to write obsolete in the XML comments...
Update: I'm using .NET 2.0
EDIT: After reading a MS Connect article, it appears that .Net 2.0 has a 'feature' where it makes ObsoleteAttribute equivalent to XmlIgnoreAttribute without any notification in the documentation. So I'm going to revise my answer to say that the only way to have your cake and eat it too in this instance is to follow #Will's advice and implement serialization manually. This will be your only future proof way of including Obsolete properties in your XML. It is not pretty in .Net 2.0, but .Net 3.0+ can make life easier.
From XmlSerializer:
Objects marked with the Obsolete Attribute no longer serialized
In the .NET Framework 3.5 the XmlSerializer class no longer serializes objects that are marked as [Obsolete].
Another workaround is to subscribe to XmlSerializer.UnknownElement, when creating the serializer for the datatype, and then fix old data that way.
http://weblogs.asp.net/psteele/archive/2011/01/31/xml-serialization-and-the-obsolete-attribute.aspx
Maybe consider to have the method for subscribing as a static method on the class for datatype.
static void serializer_UnknownElement(object sender, XmlElementEventArgs e)
{
if( e.Element.Name != "Hobbies")
{
return;
}
var target = (MyData) e.ObjectBeingDeserialized;
foreach(XmlElement hobby in e.Element.ChildNodes)
{
target.Hobbies.Add(hobby.InnerText);
target.HobbyData.Add(new Hobby{Name = hobby.InnerText});
}
}
I have struggled with this a lot - there is no solution other than doing serialization manually or using another serializer.
However, instead of writing shims for each obsolete property which quickly becomes a pain, you could consider adding an Obsolete prefix to property names (e.g. Foo becomes ObsoleteFoo. This will not generate a compiler warning like the attribute will, but at least it's visible in code.
1) WAG: Try adding the XmlAttributeAttribute to the property; perhaps this will override the ObsoleteAttribute
2) PITA: Implement IXmlSerializable
Yes I agree with marking things with the name "Obsolete" we do this with Enum values
/// <summary>
/// Determines the swap file location for a cluster.
/// </summary>
/// <remarks>This enum contains the original text based values for backwards compatibility with versions previous to "8.1".</remarks>
public enum VMwareClusterSwapFileLocation
{
/// <summary>
/// The swap file location is unknown.
/// </summary>
Unknown = 0,
/// <summary>
/// The swap file is stored in the virtual machine directory.
/// </summary>
VmDirectory = 1,
/// <summary>
/// The swap file is stored in the datastore specified by the host.
/// </summary>
HostLocal = 2,
/// <summary>
/// The swap file is stored in the virtual machine directory. This value is obsolete and used for backwards compatibility.
/// </summary>
[XmlElement("vmDirectory")]
ObseleteVmDirectory = 3,
/// <summary>
/// The swap file is stored in the datastore specified by the host. This value is obsolete and used for backwards compatibility.
/// </summary>
[XmlElement("hostLocal")]
ObseleteHostLocal = 4,
}
You may try the following workaround:
add a method named
ShouldSerializeOldObject ()
{
return true;
}
ShouldSerializeAnotherOldObject ()
{
return true
}
this may override the obsolete Attribute

Categories